【问题标题】:C program links to wrong version of functionC 程序链接到错误版本的函数
【发布时间】:2012-10-23 15:10:48
【问题描述】:

我正在尝试调试调用错误版本的函数导致段错误的问题。我正在编译的代码是机器生成的,并且包含一个名为“times”的函数,该函数将它的两个参数相乘。此代码在链接到更高级别的目标文件之前被编译为 .o。

当运行这段代码时,segfaults 和 gdb 表明它在 glibc 的 'times' 版本中,它甚至不接受相同数量的参数。在此代码中的任何地方都没有 '#include 的实例。

将时间名称更改为 times1 可以解决问题。这不是一个长期的解决方案,但由于代码的机器生成性质,并且一直手动编辑此函数的名称并不吸引人。

整个混乱编译使用 -Wall 进行清理,所以我不确定在哪里看。有关如何解决此问题的任何想法?

Compile chain:
    gcc -Wall -I. -g --shared -o dpd.o -fPIC *.c (mahine generated code here)
    gcc -g --std=c99 -c -fpic getData.c -I/usr/local/include -L/usr/local/lib -lmatio -I/usr/local/include/iverilog -I$(MATLAB)
    gcc -g -shared -o getData.vpi getData.o $(MATLAB)/dpd.o -lvpi -lmatio -L/usr/local/lib

【问题讨论】:

  • 将多个 C 文件编译为单个 .o 并不常见。如果times.c是该组编译的几个C文件之一,则可以说明问题。
  • #include 只引入声明;它无法控制链接。如果您声明一个名为times 的函数然后调用它,编译器将生成一个目标文件,该文件在其符号表中包含对该名称的引用,然后链接器将在生成最终可执行文件时搜索该名称的定义. libc 中有一个times 函数,这就是链接器找到的。
  • 基因 - 你能详细说明你的评论吗? times.c 确实是一个单独的 C 文件,它被编译到该单个对象中。为什么你会认为这会导致问题?我对这个 .o 感兴趣的切入点确实只有一个,而“times”不是其中之一。即它应该完全是内部的,而不是被视为更高层的动态符号。有没有办法告诉 gcc 这件事?
  • 很抱歉不清楚。 gcc --shared ... *.c ... 行对构建 .o 文件没有意义。 glob *.c 将捕获目录中的所有 .c 文件。 -shared 选项通常用于构建共享库,它是 Linux 中的 .so 文件或 gcc 的 Windows 版本中的 .dll。我不知道--shared 会做什么。也许什么都没有。您需要一个类似gcc -c times.c 的命令,并且对于彼此生成的文件类似。然后在最终命令中链接所有生成的.o 文件。
  • Brian,dpd.o 在链接行中以$(MATLAB)/ 为前缀但在编译行中没有任何意义?你也可以试试-nodefaultlibs吗?

标签: c linker glibc


【解决方案1】:

C 仅使用函数的名称作为标识符,因此任何两个(导出的)同名函数都会发生冲突。正常的方法是在库中为所有导出的名称添加一个唯一前缀。另一种选择是将 C++ 用作“更好的 C”,并使用 C++ 编译器简单地构建 C 代码,利用 C++ 名称修饰。

【讨论】:

  • 在这种情况下链接器不应该被“重复符号”阻塞吗?
  • 除非你强迫它拖入两个不同的 .o 文件,其中有相同的符号。
  • @H2CO3 UNIX 链接器 从不 在主可执行文件和共享库中定义相同的符号(此处为 libc.so.6)时抱怨 - 这种符号插入很常见,并且通常非常有用。
【解决方案2】:

所以这个问题的真正答案是将-fno-builtin-times 扔给gcc。这样可以轻松避免问题。

这当然假设您不能将 times 的名称更改为与 glibc 提供的函数不冲突的名称。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-10-10
    • 2015-12-05
    • 1970-01-01
    • 1970-01-01
    • 2020-09-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多