【问题标题】:Undefined reference when dynamically linking with gcc in cygwin在 cygwin 中与 gcc 动态链接时未定义的引用
【发布时间】:2012-02-16 19:30:13
【问题描述】:

(这是gcc 3.3.1(长篇故事——归咎于 NIST)Cygwin。)

我用gcc -c -fPIC ...编译了一些源文件来获取.o文件。

然后我做了:

$ gcc -shared -o foo.dll foo.o bar.o

但是当我去使用它时:

$ gcc -o usefoo.exe usefoo.o -L. -lfoo
  usefoo.o:usefoo.cpp:(.text+0x2e0): undefined reference to `_get_template_size'
  collect2: ld returned 1 exit status

但是,如果使用相同的 .o 文件,我会改为:

$ ar rcs libfoo-static.a foo.o bar.o

链接成功:

$ gcc -o foo.exe foo.o -L. -lfoo-static

对我来说奇怪的是,正如您在下面看到的,有问题的引用存在于 .a 和 .dll 中。那么为什么链接 .dll 时会出现错误?

在共享库中找到参考:

$ nm foo.dll|grep get_template
1001b262 T _get_template_size

而且它也在静态库中:

$ nm libfoo-static.a |grep get_template
00000352 T _get_template_size

这里是对要使用该函数的文件中生成的符号的引用:

$ nm usefoo.o
00000000 b .bss
00000000 d .data
00000000 t .text
0000012c T __Z12ErrorMessagei
         U ___main
         U __alloca
         U _atoi
         U _get_template_size
0000026c T _main
         U _printf

已更新以解决 Marco 的回答

有趣/烦人的是,当我尝试对此做一个最小的测试示例时,我无法做到(尽管每次都会发生真实的事情):

func1.h

#ifndef FUNC1_H
#define FUNC1_H

int func1(int i);

#endif

func1.c:

#include "func1.h"

int func1(int i) {
  return 2*i;
}

usefunc.c

#include <stdio.h>
#include "func1.h"

int main() {
  printf("%d\n", func1(10));
}

然后:

$ rm *.o *.dll *.a

$ gcc -fPIC -I. -c func1.c usefunc.c

$ gcc -shared -o func.dll func1.o

$ gcc -L. -o usefunc.exe usefunc.o -lfunc

$ ./usefunc.exe
20

【问题讨论】:

    标签: c gcc linker cygwin dynamic-linking


    【解决方案1】:

    我在 Cygwin 网页上找到了答案(因为它解决了我的链接问题):http://cygwin.com/cygwin-ug-net/dll.html

    我最终要做的是创建共享库并像这样执行最终链接:

    $ gcc -shared -o cygfoo.dll \
          -Wl,--out-implib=libfoo.dll.a \
          -Wl,--export-all-symbols \
          -Wl,--enable-auto-import \
          -Wl,--whole-archive *.o \
          -Wl,--no-whole-archive
    
    $ gcc -L. -o usefoo.exe usefoo.o -lfoo
    

    但我仍然很想知道为什么我的简单测试不必这样做。

    【讨论】:

      【解决方案2】:

      我不完全确定,但 afaik Windows 每个模块都有命名空间(如 exe 或 .dll)。静态链接时,您将所有内容都放在一个 .exe 中,即一个模块,一个命名空间。

      动态链接时,您创建了两个模块(1 个 exe,1 个 dll),它们都有自己的命名空间。

      您需要从 DLL 中导出符号才能使用 iirc(阅读 importlibs,例如在优秀的 Linkers and Loaders

      【讨论】:

      • 有趣!有两点需要注意:(1)对于有问题的实际代码,如果我在共享库中添加对其他事物的调用,它们也会在动态链接下显示为未定义——所以它不仅仅是那个特定的函数。这支持你的答案。但是......(2)当我尝试对此进行简单测试时,简单测试在动态链接下工作正常! (请参阅我的问题的更新)。
      • 不知道。编译器中可能有辅助功能,我不太了解各种 Windows 端口。 Windows 上的 Btw PIC ?!?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多