Windows下MinGW生成动态库报未定义符号错误 Linux无该问题如何解决
问题描述
现有名为helloworld.c的源文件,依赖外部动态库libhello.dll,对应代码如下:
/* helloworld.c */ #include <stdio.h> void hello(void); int main() { hello(); return 0; }
需求是将helloworld.c编译为动态库,在Windows系统安装MinGW后,最初执行如下编译命令:
gcc -shared -fPIC -o libhelloworld.dll hello_world.c
命令执行后出现如下报错:
undefined reference to `hello' collect2.exe: error: ld returned 1 exit status
经测试,必须显式指定依赖的动态库才能完成编译,可正常执行的命令如下:
gcc -shared -fPIC -o libhelloworld.dll hello_world.c -L. -lhello
已知Linux环境下生成动态库时默认允许存在未定义符号,无需提前显式指定依赖库即可完成编译,Windows下MinGW默认不支持该特性。疑问:是否可以通过添加编译参数等配置方式,让Windows下MinGW生成动态库时的行为与Linux一致,无需通过-L、-l参数指定依赖动态库的路径与名称?
解答
可以实现,给链接器传递--allow-shlib-undefined参数即可。由于gcc本身不识别链接器专属参数,需要通过-Wl,前缀将参数传递给ld,修改后的编译命令如下:
gcc -shared -fPIC -o libhelloworld.dll hello_world.c -Wl,--allow-shlib-undefined
行为差异原因
- Linux下生成ELF格式动态库时,ld默认开启未定义符号允许规则,生成so阶段不会强制解析所有外部符号,符号解析工作可以推迟到最终可执行文件链接、甚至程序加载运行阶段完成,因此编译中间动态库时不需要提前指定所有依赖。
- Windows下PE格式动态库默认要求生成阶段就完成所有符号解析,MinGW链接器默认沿用PE格式的这个链接规则,因此未显式指定依赖时会直接抛出未定义引用错误。
注意事项
- 该参数仅跳过dll生成阶段的依赖符号检查,不会改变运行时依赖逻辑,最终程序运行时仍然需要保证
libhello.dll在系统dll搜索路径中,否则会出现加载失败问题。 - MinGW编译Windows动态库时
-fPIC参数不是必填项,x86、x64架构的Windows PE格式本身已处理位置无关逻辑,加该参数无副作用但非必须。 - 该参数仅能简化中间动态库的编译命令,后续将
libhelloworld.dll链接到最终可执行文件时,仍然需要把全链路依赖的库都通过-l参数指定给链接器。
内容的提问来源于stack exchange,提问作者super_jh
相关产品推荐
相关产品推荐

