我在Windows 7下的Cygwin中使用gcc 4.3.4和ld 2.20.51。这是我的问题的简化版本:
foo.o
包含在bar.o中调用foo_bar()
的函数bar()
bar.o
包含函数bar()
main.c
调用foo.o
中的函数,但foo_bar()
不在调用链中如果我尝试编译main.c并将其链接到foo.o,我会从ld收到undefined reference to _foo_bar
错误。正如您在Makefile中看到的那样,除了下面之外,我已经尝试使用标志将每个函数放在它自己的部分中,并让链接器丢弃未使用的部分。
COMPILE_CYGWIN = gcc -iquote$(INCDIR)
COMPILE = $(COMPILE_CYGWIN) -g -MMD -MP -Wall -ffunction-sections -Wl,-gc-sections $(DEFINE)
main_OBJECTS = main.o foo.o
main.exe : $(main_OBJECTS)
$(COMPILE) -o main.exe $(main_OBJECTS)
函数foo_bar()
是一个简短的函数,它提供协议栈中两个网络层之间的连接。某些程序不需要它,因此它们不会链接到与堆栈上层相关的其他目标文件中。这是一个小功能,似乎不适合将它放入自己的.o文件中。
我不明白为什么ld会抛出错误 - 没有任何东西正在调用foo_bar()
,所以不需要在最终的可执行文件中包含bar()
。一位同事刚刚告诉我,ld
不是一个“智能连接器”,所以也许我想做的事情是不可能的?
答案 0 :(得分:7)
除非链接器来自Cyberdyne Systems,否则无法确切知道实际调用哪些函数。它只知道引用了哪些。即使Skynet's链接器无法预测将在运行时动态加载模块并且它开始调用各种全局函数 1 ,将会做出什么样的运行时决策。 / p>
所以, if 你在模块 m 中链接并引用函数 f ,你需要链接任何模块 ˚F
1。此问题与 Halting Problem 有关,并已经过验证 undecidable 。
答案 1 :(得分:2)
我遇到了类似的问题,我找到了这个页面: http://lists.gnu.org/archive/html/bug-gnu-utils/2004-09/msg00098.html Highligt: GNU链接器仍然以.o文件粒度工作。 Gcc拉入foo.o,然后发现bar()未定义。
你最好把foo_bar()放到另一个.o文件中。