【问题标题】:gcc linking differently of g++gcc 与 g++ 的链接方式不同
【发布时间】:2012-10-14 13:38:18
【问题描述】:

我将 C++ 代码转换为 C,现在我也在尝试更改 Makefile。我有这个:

g++ -fPIC -o bin/linux/release/gpu_md5 cuda_md5.c cuda_md5_cpu.c obj/release/cuda_md5_gpu.cu.o 
-L/usr/local/cuda/lib64 -L../../lib64 
-L../../common/lib64/linux -L/opt/cuda/NVIDIA_CUDA_SDK/lib64 -lcudart     
-L/usr/local/cuda/lib64 -L../../lib64 
-L../../common/lib64/linux -L/opt/cuda/NVIDIA_CUDA_SDK/lib64

据我所知,我可以将 g++ 更改为 gcc,它应该可以正常工作,但事实并非如此。看起来 gcc 无法从 cuda_md5_cpu.c 中找到我在 cuda_md5.c 中调用的函数(PS:我在 cuda_md5.c 中不包括 cuda_md5_cpu.c):

/tmp/ccKdDJiq.o: In function `cuda_compute_md5s':
cuda_md5.c:(.text+0x201): undefined reference to `init_constants'
cuda_md5.c:(.text+0x2e2): undefined reference to `execute_kernel'
collect2: ld returned 1 exit status

怎么了?我刚从 g++ 改成了 gcc。

【问题讨论】:

    标签: gcc g++ dynamic-linking


    【解决方案1】:

    我想说obj/release/cuda_md5_gpu.cu.o(您似乎没有重新编译)很有可能是用 C++ 编译器编译的,因此符号名称已被名称修改修改。

    名称修饰是 C++ 编译器使用的一种技术,允许不同的函数具有相同的名称但具有不同的参数类型(重载),而 C 编译器不需要这样做,因为不允许重载。

    换句话说,您可能会发现 init_constants(int,float); 可能会被 C 编译器简单地变形为 _init_constants,但是,如果您使用 C++ 编译器,您会得到类似 _init_constants_$$_IntFloat 的内容,以便将其与init_constants(int,double)init_constants(void)

    因此,尝试将 C 编译的 cuda_md5.c 与 C++ 编译的 obj/release/cuda_md5_gpu.cu.o 链接在一起的链接器将无法将函数名称匹配在一起。

    这就是您经常在 C++ 代码中看到 extern "C" { ... } 的原因,它使用 C 规则将函数名称(和其他内容)导出到链接器,以允许将 C 和 C++ 代码链接在一起。

    【讨论】:

    • 我很确定我不再使用 g++,这里是 makefile pastebin.com/Abnh7Vm2
    • @FredericoSchardong,我敢肯定你不是。但问题是 CUFILES 没有与 makefile 一起编译,它们被添加到 OBJS 列表中,这意味着它们已经编译了。如果它们是用 C++ 编译器编译的(没有extern C),你就会遇到这个问题。
    • @FredericoSchardong,你需要告诉我们。你能在 Makefile 输出中看到它的编译吗?如果依赖项比目标文件更新,它只会这样做(基于第 344 行)。如果没有,目标文件将保持原样。您还应该能够通过使用nm 或类似工具查看该目标文件中的符号来判断。
    • 我在编译之前删除了所有 *.o,而且我看到 cuda_md5_gpu.cu.o 正在创建。抱歉我的无知,nm是什么?
    • @FredericoSchardong, nm 是一个 UNIX 工具,用于显示目标文件中的符号。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-19
    • 2010-11-03
    • 1970-01-01
    • 1970-01-01
    • 2018-10-17
    相关资源
    最近更新 更多