例如,假设我构建了一个包含两个文件的库a.lib:foo.c和bar.c。 foo.c调用在bar.c中定义的函数void bar()
。
现在让我们说我要创建一个具有两个文件的可执行文件:main.c和bar.c。此bar.c还定义了void bar()
,但实现方式不同。
当我将可执行文件与a.lib链接时,可执行文件将调用哪个void bar()
?
答案 0 :(得分:1)
让我们假设:
libfoobar.a
(或libfoobar.lib
),位于目录./lib
中。foo.c
定义了foo()
和foo()
调用bar()
。bar.c
定义了bar()
。bar.c
还定义了bar()
-一种不同的实现。main.c
调用foo()
和bar()
。您的链接命令行如下:
cc -o program main.o bar.o -L ./lib -lfoobar
然后:
bar()
中的bar.c
(因为该文件已明确包含在命令行中,位于库的前面)。foo()
中的foo.c
,但是它调用的bar()
将是程序文件bar.c
中的那个foo.c
从图书馆。如果涉及更多符号,则库bar.c
调用仅在库bar.c
中可用的函数(程序bar.c
并未实现所有这些函数),然后链接将失败,因为程序(无条件地)包含程序的bar.c
,但是它也需要库的bar()
,但这为函数bar.c
提供了双重定义-这是一个错误。
曲折可能变得严重。简单的经验法则—不要这样做。也就是说,请勿使程序的bar.c
提供库bar()
中也可用的符号。如果必须并且还涉及其他切入点,那么您就必须加倍努力。
不要将库放在目标文件之前;那么您将无法通过双重定义aInstance = new A();
class B {
anotherMethod = aInstance.someMethod;
}
而失败。库位于链接列表中的目标文件之后。不过,您确实需要以正确的顺序获取多个(静态)库。或使用特殊选项使加载程序重新扫描库等。