3

我最近写了一些字符串例程的替代品(memcpy、memset 和 memmove)。我的理解是,如果在编译/链接行中指定了包含这些例程的库,这些将优先于同名的系统标准库例程。如果我已经错了,请告诉我!

这在我所做的所有测试中都能正常工作(通过反汇编验证存在正确的例程而 glibc 例程不存在),但进一步的测试发现了一个由此引起的奇怪中断:

1)用-g在同一个库中构建另一个文件(我一直在构建-O2)

2) 这个文件有一个显式调用 memset

3a) 如果编译时选项的工作方式是这个 memset 被 gcc 内联,那么一切正常

3b) 但是,如果这些选项禁用了本应内联的 memset 调用的内联,则该库将构建,但使用该库静态链接应用程序会导致重复符号链接器错误 - 该符号的另一个实例是系统库的 memset。

基本上我可以构建我的库的两个版本(100 个源文件),并且通过将一个目录中的 make CFLAGS 从 -O1 -g 更改为仅 -g 我可以在使用该库时触发链接器错误。

我可以使用工作版本,通过 nm 运行它,并看到它有许多对 memset 的未定义引用,包括链接到我的测试用例的例程 - 所以我知道它应该尝试在工作用例中解析 memset。当我将此与损坏库的 nm 输出进行比较时,我看到的只是一些额外的未定义的 memcpy 和 memset 引用。如果 memset 在第一种情况下(对我的例程)解决了,它应该在第二种情况下解决。

我还查看了详细的编译器输出并验证了两种情况下的链接行完全相同,除了这个库的路径。

这里有两个超级令人费解的事情(在无数其他问题中):

1)为什么构建的库中的文件 -O1 -g 链接与 -g 不同

2) 为什么用户库中的替换 memset 会与系统 memset 冲突

而对于大奖,1)如何导致2)

4

2 回答 2

2

想出这个解决方案花了很长时间,但现在很有意义:

1) 更高的优化使 gcc 能够内联 bzero,在链接时它没有其他引用。memset 称它是内联/不是内联是红鲱​​鱼。

2) bzero 与 libc.a 中的 memset 位于同一文件中:memset.o。当 ld 试图拉入 memset.o 以满足 bzero 请求时,它得到了重复的 memset 符号。

(1) 原因 (2)。

解决方案是在我的库中提供我自己的 bzero 例程,从而停止需要 libc 的 memset.o。

于 2013-07-10T19:08:00.580 回答
1

GCC 提供了大量标准库函数的内置版本。这些是为了优化目的而提供的。

其中许多功能仅在某些情况下进行了优化。如果它们在某种情况下未优化,则会发出对库函数的调用。

因此,构建的库 -O1 -g 的链接方式与 -g 不同。

于 2013-07-10T06:36:14.377 回答