【问题标题】:How to detect multiply defined symbols如何检测多重定义的符号
【发布时间】:2012-09-25 00:00:18
【问题描述】:

我有一个常见的场景: 可执行文件的一些源文件依赖于一些标准库和一些用户库。所有用户库都静态链接到可执行文件,而标准库则动态链接到它。

问题: 我相信我在完整的包中已经定义了多个符号(可执行文件已经包含用户库代码+共享标准库)。链接器显然对它有洞察力,但据我了解,除非遇到多个强命名符号,否则链接器不会抱怨。我担心的是,当我将代码从 solaris 8/sparc 平台移动到 solaris10/sparc 平台时,一些标准的 unix 函数已经在用户库中实现,这会导致应用程序在运行时崩溃。请注意,该应用在 solaris 8/sparc 平台上运行良好

我一直面临着奇怪的问题,这让我相信这可能是源头

  1. 修改一个库中的一个变量正在更改另一个库中另一个变量的值
  2. Solaris 8-10: host2ip conversion problems

我需要什么:

  1. 有没有办法轻松列出所有多重定义的符号?
  2. 有没有一种方法可以轻松列出源自用户库的所有多重定义符号?
  3. 你们认为问题 #1 可能是由链接问题引起的,还是您认为这可能是其他问题的征兆?

编辑1: 从那时起,我知道在使用 ld 生成映射文件时,它有一段多重定义的符号,我将通过它来查找看起来像标准库调用的名称。对于不知道的人,链接器只有在找到多个具有相同名称且名称是强名称的符号时才会链接失败。

【问题讨论】:

    标签: c++ unix linker porting


    【解决方案1】:

    您可以在编译器(实际上是链接器)设置中打开 MAP 文件生成,并在映射文件中查找与您关注的 UNIX 系统函数匹配的符号。您可能必须编写一个脚本来自动化它,但这将是一个很好的起点。命令行开关可能是 -map 或类似的东西,这取决于您使用的编译器/链接器。

    【讨论】:

    • 我正在尝试理解地图文件。如果您能详细说明它将如何提供帮助,那就太好了。我正在使用“ld -m”通过gcc前端生成的地图文件,它显然没有符号
    • @IDK 我不确定大小写是否重要,但请确保您使用的是链接器选项 -Map=mapfile.map (如果通过 gcc,-Wl,-Map=mapfile.map )地图)。符号名称及其位置将生成到映射文件中。然后,您将寻找与 unix/stdlib 函数(例如 inet_ntoa_r)同名的符号。这是您可能必须编写脚本的部分。
    • ld 不采用该选项。我尝试了 gcc-2.95.2 -Wl,-Map=mapfile.map 并得到错误 ld: fatal: file ap=mapfile.map: stat failed: No such file or directory 因为 -M 是它认为的选项
    • 我想将您的建议标记为答案之一,但我想我只能选择一个
    【解决方案2】:

    实际发生的问题是: 该库(我们称之为 lib1)有一个如下所示的数组

    #define ARRAY_SIZE 1024
    SomeStruct* global_array[ARRAY_SIZE];
    

    这个数组被我的另一个库(我们称之为 lib2)使用,而我的应用程序又使用它来使用它的外部声明。

    在编译 lib2 时(或者应用程序不确定),我们根本没有定义 ARRAY_SIZE。这以某种方式导致 lib2(或应用程序)的编译器错误地计算 global_array 的大小,进而导致它在已经分配给 global_array 的位置为其他变量分配内存。

    通过在编译我的库和应用程序时再次定义 ARRAY_SIZE,一切都开始正常运行。由于数组的 extern 声明不包含大小,我不完全理解是什么导致了这个问题以及为什么它得到了解决。另外,如果库真的使用了 MACRO ARRAY_SIZE,那为什么编译不会失败呢?此外,用于定义的名称有可能是标准名称(实际字符串为 FD_SETSIZE)

    我最初对链接器的直觉是错误的。

    【讨论】:

      猜你喜欢
      • 2012-02-22
      • 1970-01-01
      • 2020-12-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多