我在 clang 中发现了错误,并将其发布在这里,因为很难找到如何在 clang 系统中执行此操作。我认为这些信息很有用 - 我在网上看到了类似的问题。
因此,clang 进行了错误的链接。它是 OpenBSD 6.3 amd64,稳定。
当模块之一具有与库函数同名的全局变量时,它将库函数调用链接到变量,即使变量的类型为“int”。例子:
主(简单)模块“socket.cpp”,调用 socket():
#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 进行编译并链接它们,而不会发出警告。但是当您运行该程序时 - 您会收到“分段错误”。
如果我在反汇编程序中看到可执行文件,我会看到 - 没有调用系统函数“socket”。它以丑陋的方式“调用”这个变量。
如果有人知道如何向 clang 社区提交此错误报告,请...
更新1
clang 被如下调用:
clang -o test socket.o add.o
更新2
嗯,我想这是预料之中的。链接器应该如何区分两个套接字符号? – 箭头
Microsoft编译器如何区分呢?技术难度很大?这段代码在 Visual Studio 中运行良好。那里不是问题。
更新3
然后代码“调用”它,从而导致崩溃。这不是一个错误。 – 箭头
在程序员的逻辑中这是BUG。如何调用变量“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 函数和全局变量不使用重整。