나는 clang에서 버그를 발견했고 clang 시스템에서는 이 버그를 수행하는 방법을 찾기가 어렵기 때문에 여기에 게시하고 있습니다. 이 정보가 유용하다고 생각합니다. 온라인에서 비슷한 질문을 본 적이 있습니다.
따라서 clang은 잘못된 연결을 수행합니다. OpenBSD 6.3 amd64이며 안정적입니다.
모듈 중 하나에 라이브러리 함수와 이름이 같은 전역 변수가 있으면 변수 유형이 "int"인 경우에도 라이브러리 함수 호출을 변수에 연결합니다. 예:
기본(단순) 모듈 "socket.cpp", 소켓() 호출:
#include <stdio.h>
#include <sys/socket.h>
int
main(int argc, char * argv[]){
int result = socket(AF_INET, SOCK_DGRAM, 17);
printf("result = %d\n", result);
return 0;
}
두 번째 모듈 "add.cpp"에는 "socket"이라는 전역 변수가 있습니다.
int socket = 5;
makefile/clang을 사용하여 경고 없이 컴파일하고 링크할 수 있습니다. 그러나 프로그램을 실행하면 "세그먼트 오류"가 발생합니다.
디스어셈블러의 실행 파일을 보면 시스템 함수 "소켓"에 대한 호출이 없습니다. 이 변수는 추악한 방식으로 "호출"됩니다.
이 버그 보고서를 clang 커뮤니티에 제출하는 방법을 아는 사람이 있다면, 제발...
업데이트 1
clang은 다음과 같이 호출됩니다.
clang -o test socket.o add.o
업데이트 2
뭐, 그건 예상할 수 있을 것 같아요. 링커는 두 소켓 기호를 어떻게 구별해야 합니까? – 화살
Microsoft 컴파일러는 어떻게 차별화됩니까? 기술적으로 어려운가요? 이 코드는 Visual Studio에서 제대로 실행됩니다. 거기에는 문제가 없습니다.
업데이트 3
그러면 코드가 이를 "호출"하여 충돌이 발생합니다. 이것은 실수가 아닙니다. – 화살
이것은 프로그래머 논리의 버그입니다. 변수 "int"를 호출하는 방법은 무엇입니까? 이 디자인의 특정 인체 공학적 특성은 좋지 않습니다.
링커가 "호출" 변수 "int"를 언급하지 않는 이유는 무엇입니까? 이것은 말도 안되는 소리입니다. 이것은 잘못된 시스템 설계입니다.
연결 프로세스의 모호함을 경고해야 합니다. 침묵의 행위 - 실수의 봄.
답변1
이는 정수를 함수로 실행하려고 하기 때문에 발생합니다. int socket = 5;
함수와 동일한 이름을 사용하면 socket()
다음과 같이 이를 달성하는 더 쉬운 방법이 있습니다.
$ cat main.c
int main = 9;
$ clang -Wall main.c
$ ./a.out
Segmentation fault
업데이트: @Kusalananda가 댓글에서 언급했듯이 clang에서만 발생하는 것은 아닙니다.
답변2
링커는 socket
기호를 정수 변수로 해석합니다. 그러면 코드가 이를 "호출"하여 충돌이 발생합니다. 이것은 실수가 아닙니다.
내보낸 모든 기호를 장식하기 위해 특별한 장식 구성표를 사용하기 때문에 Microsoft 컴파일러와 함께 작동합니다. 이 시나리오에서는 C 함수와 전역 변수가 다르게 장식되어( ?socket@@YAHHHH@Z
vs ?socket@@3HA
) 기호 이름이 달라집니다. *nix 시스템에서는 일반 C 함수와 전역 변수가 리매핑을 사용하지 않습니다.