c-无声符号碰撞



之前在Raspberry Stackeexchange上发布过,作为非主题关闭,所以我在这里。

以下程序使用gcc main.c -lpigpio -lpthread -Wall -Wextra进行了干净的编译。我使用的是gcc 8.3.0(交叉编译器或普通编译器不会更改任何内容(。

// main.c
#include <stdio.h>
#include <pigpio.h>
void listen() {
printf("hi from listenn");
}
int main() {
gpioInitialise();
printf("hi from mainn");
gpioTerminate();
return 0;
}

没有警告,但程序愉快地打印

hi from listen
hi from main

原因似乎是gpioInitialise()试图从这里的<sys/sockets.h>调用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(不被声明为静态那样简单吗?

Linker允许您插入这样的符号,用于调试、分析等目的。不幸的是,在链接阶段,键入信息通常不可用,因此链接器无法执行任何健全性检查来验证预期签名和实际签名是否匹配。有人可能会说,有了-g,这是可能的,但没有人足够关心实现这一点(尽管这可能是一个好的家庭项目(。

Static在您的情况下会有所帮助,因为它可以防止listen被导出和libc的listen被重写。

顺便说一句,在ELF系统(Linux(上,情况越来越糟,因为它们允许运行时符号插入(即,库在程序启动时竞争谁赢得符号名称(。这通常通过static-fvisiblity=hidden来解决(不幸的是,许多库不使用它们(。

最新更新