2015-01-22 1 views
3

링커가 함수 매개 변수 검사를하지 않는다고 말하는 것이 맞습니다. 함수 호출의 수 또는 유형을 확인하거나 전역 데이터 참조 유형을 확인하지 않습니다. 모든 링커에게 이것이 사실입니까?C 또는 C++ 링커에서 유형 검사가 있습니까?

저는 Clang을 사용하여 x86-64에서 Linux를 사용하고 있습니다. 링커가 참조가 올바른 세그먼트에 있는지 확인합니까? 또는 링커에 관한 한 외부 참조는 사실상 무효 *일까요?

저는 높은 수준의 언어 배경 C#과 Scala에서 왔습니다. 따라서 저수준 세계에 몰입 한 사람들에게는 이것이 분명해 보일 수 있습니다. 어셈블러에 몇 가지 함수 (시스템 호출)를 작성했으며 어셈블러에 외부 함수에 대한 매개 변수 프로토 타입이 없다는 것을 알았습니다.

컨텍스트 : 저는 실제로 컴파일러를 작성하고 있습니다. 지금은 시스템 호출을 위해 어셈블러 함수로 전처리 된 C.i 파일을 대상으로하고 있지만 대안은 C++, 어셈블러 또는 기계 코드이기 때문에 비용 및 이점, 특히 유형 검사의 중요성을 평가하려고합니다. 어셈블러/컴파일러/링커 내 자신의 프로그램과 함수 프로토 타입 생성의 정확성을 검사하는 데 사용할 수 있습니다.

+1

아마 이런 유형의 오류가 발생하지 않았 으면 컴파일러는 연결하기 전에 오류가 발생했을 것입니다. – CoryKramer

+1

Cyber가 맞습니다 - 원칙적으로 링커는 주소 (물론 심볼 이름) 만 처리합니다. –

+9

C++에서 이름은 (일반적으로?) 형식으로 변경되므로 형식이 일치하지 않으면 기호를 찾지 못하게됩니다. 이는 주로 함수 오버로드 기능 때문입니다. 나는 함수가 아닌 변수에 대해서는 모른다. C++의 링크 단계는 불분명하고 맹 글링은 일관성이 없습니다 (실제로 다른 컴파일러는 다른 방법으로 기호를 조작합니다). 그래서 평소보다 더 말할 수는 없습니다. C에서는 오버로드가 불가능하기 때문에 형식이 지정되지 않았습니다 (일반적으로?). C의 link-stage 스펙에 대해 충분히 알지 못하지만 일관성이 있습니다. – Yakk

답변

7

@ Yakk이 설명했듯이 함수는 매개 변수를 기반으로 오버로드 될 수 있으므로 컴파일러는 매개 변수와 해당 형식에 대한 정보가 포함 된 변환 된 함수 이름을 생성합니다. 링커는 대부분 심볼 이름과 크기를 확인하지만, 맹 글링은 함수의 이름이 다르다는 것을 보장하므로 불일치 된 매개 변수는 연결되지 않습니다. (리턴 타입에 과부하가 불법이기 때문에) 당신은 하나 개의 번역 단위에서 int test()을 선언하고 다른에 float test()를 호출 할 경우, 그래서 맹 글링의 일부가 아닌

기능 반환 형식, 링커는 그것을 잡을 수 없습니다 , 그리고 당신은 나쁜 결과를 얻을 것이다.

마찬가지로 글로벌 변수 유형 (클래스의 정적 멤버 등)은 링커에서 검사하지 않으므로 extern int test;을 하나의 번역 단위로 선언하고 float test;을 다른 언어로 정의하면 잘못된 결과가 표시됩니다. .

링커는 경우에 따라 두 개의 다른 번역 단위로 기호의 크기을 비교할 수 있으며 이러한 방식으로 몇 가지 문제점을 파악할 수 있습니다.

실제 C++ 개발에서는 거의 문제가되지 않습니다. 왜냐하면 함수 또는 변수 또는 클래스가> 1 번역 단위에 필요할 때마다 두 번역 단위에 포함 된 헤더 파일에 선언 할 것이므로 컴파일러는 링커가 실행되기 전에 오류를 잡을 것입니다. (문제가 될 수있는 한 가지 경우는 외부 바이너리 라이브러리를 사용하고 있고 헤더 파일이 라이브러리와 일치하지 않는 경우입니다.)

+2

실제로 외부 라이브러리의 내용과 일치하지 않는 헤더 파일을 사용하면이 문제가 발생할 수 있습니다. – PypeBros

+0

@PypeBros - 좋은 지적입니다. 나는 나의 대답을 업데이트했다. 감사. –

+0

@ JoshKelley 감사합니다. 다른 번역 단위로 sizeof를 확인하는 것에 대한 더 많은 정보가 있습니까? –

3

모든 컴파일러는 오버로드 된 기능을 분리하기 위해 일부 형식의 이름 변환을 구현합니다. 그러나 반환 유형은 mangle에 포함되지 않으므로 (보통) 같은 문제가 여기에 존재할 수 있습니다.

C에서는 올바른 것입니다. 링커에서 검사 할 수는 없지만 생각만큼 심각하지는 않습니다. 컴파일러는 함수에 대한 호출이 제공된 헤더와 일치하는지 확인 했으므로 문제를 일으키는 유일한 방법은 나중에 링크 된 두 개의 다른 C 파일로 컴파일 된 헤더 파일의 다른 중복 버전을 갖는 것입니다.

실수로 처리하기가 어렵습니다 (관리하는 경우 약간의 오류가 발생할 수 있음).

0

많은 링커에는 일정 수준의 유형 검사를 제공하는 기능이 포함되어 있지만 세부 사항은 다양합니다. 일부 컴파일러는 하나의 호출 규칙을 사용하는 함수의 이름 앞에 밑줄을 붙이지 만 다른 호출 규칙을 사용하는 함수의 이름에서 밑줄을 생략합니다. 한 번역 단위가 한 규칙을 사용하여 함수를 선언하지만 실제 함수가 다른 규칙을 사용하여 정의되면 링크시 프로그램이 거부됩니다.

일부 플랫폼 (예 : PIC 용 HiTech C)을 사용하면 컴파일러 또는 어셈블리 언어 프로그램이 기호를 선언하거나 참조 할 때 16 비트 값을 지정할 수 있으며 참조 점이 해당 값을 제공하지 않으면 스 쿼크합니다 정의와 일치하지 않습니다. C 컴파일러는 매개 변수 형식과 반환 형식의 조합을 기반으로 각 함수에 대해 해시 값을 생성하며 링커는 정의 및 호출 사이트에서 서명 해시 값이 다른 함수를 호출하려고하면 호출합니다.