无声符号碰撞?
Silent symbol collision?
之前在 Raspberry Stackexchange 上发表过,因题外话而关闭,所以我来了。
下面的程序可以用 gcc main.c -lpigpio -lpthread -Wall -Wextra
干净地编译。我正在使用 gcc 8.3.0(交叉编译器或普通编译器不会改变任何东西)。
// main.c
#include <stdio.h>
#include <pigpio.h>
void listen() {
printf("hi from listen\n");
}
int main() {
gpioInitialise();
printf("hi from main\n");
gpioTerminate();
return 0;
}
没有警告,但程序愉快地打印
hi from listen
hi from main
原因似乎是 gpioInitialise()
试图从 <sys/sockets.h>
here 调用 listen(2),而是从 main.c
调用函数。当然,这是行不通的,会导致 pigpio 库出现错误消息:
xxxx-xx-xx xx:xx:xx pthSocketThread: setsockopt() fail, closing socket -1
xxxx-xx-xx xx:xx:xx pthSocketThread: accept failed (Bad file descriptor)
问题:为什么 gcc 链接一个具有完全不同签名的函数而不抛出任何错误?我知道 static
,但我想理解这一点以从中学习。肯定不能像 listen(2) 不声明为静态那么简单?
链接器允许您插入这样的符号以用于调试、分析等目的。不幸的是,在 link 阶段,输入信息通常不可用,因此 linker 无法执行任何健全性检查来验证预期签名和实际签名是否匹配。有人可能会争辩说 -g
这是可能的,但没有人足够关心实现它(尽管这可能是一个很好的家庭项目)。
Static
会对您的情况有所帮助,因为它会阻止 listen
被导出和 libc 的 listen
被覆盖。
作为旁注,在 ELF 系统 (Linux) 上情况更糟,因为它们允许运行时符号插入(即库在程序启动时竞争谁赢得符号名称)。这通常用 static
或 -fvisiblity=hidden
解决(不幸的是很多库 do not use them)。
之前在 Raspberry Stackexchange 上发表过,因题外话而关闭,所以我来了。
下面的程序可以用 gcc main.c -lpigpio -lpthread -Wall -Wextra
干净地编译。我正在使用 gcc 8.3.0(交叉编译器或普通编译器不会改变任何东西)。
// main.c
#include <stdio.h>
#include <pigpio.h>
void listen() {
printf("hi from listen\n");
}
int main() {
gpioInitialise();
printf("hi from main\n");
gpioTerminate();
return 0;
}
没有警告,但程序愉快地打印
hi from listen
hi from main
原因似乎是 gpioInitialise()
试图从 <sys/sockets.h>
here 调用 listen(2),而是从 main.c
调用函数。当然,这是行不通的,会导致 pigpio 库出现错误消息:
xxxx-xx-xx xx:xx:xx pthSocketThread: setsockopt() fail, closing socket -1
xxxx-xx-xx xx:xx:xx pthSocketThread: accept failed (Bad file descriptor)
问题:为什么 gcc 链接一个具有完全不同签名的函数而不抛出任何错误?我知道 static
,但我想理解这一点以从中学习。肯定不能像 listen(2) 不声明为静态那么简单?
链接器允许您插入这样的符号以用于调试、分析等目的。不幸的是,在 link 阶段,输入信息通常不可用,因此 linker 无法执行任何健全性检查来验证预期签名和实际签名是否匹配。有人可能会争辩说 -g
这是可能的,但没有人足够关心实现它(尽管这可能是一个很好的家庭项目)。
Static
会对您的情况有所帮助,因为它会阻止 listen
被导出和 libc 的 listen
被覆盖。
作为旁注,在 ELF 系统 (Linux) 上情况更糟,因为它们允许运行时符号插入(即库在程序启动时竞争谁赢得符号名称)。这通常用 static
或 -fvisiblity=hidden
解决(不幸的是很多库 do not use them)。