【问题标题】:MinGW + Boost: undefined reference to `WSAStartup@8'MinGW + Boost:未定义对 `WSAStartup@8' 的引用
【发布时间】:2012-09-10 11:02:23
【问题描述】:

下面是我执行的

D:\Just4Fun\software\>make -f Makefile.hands stest
g++.exe -g -D_WIN32_WINNT=0x0601 -ID:\Boost\boost_1_51_0 -LD:\Boost\boost_1_51_0\stage\lib -LD:\MinGW\lib -lboost_system-mgw46-d-1_51 -lboost_filesystem-mgw46-d-1_51 -lboost_iostreams-mgw46-d-1_51 -lws2_32 -lwsock32 -o TestSerial.exe TestSerial.cpp

下面是那个结果

C:\Users\oleg\AppData\Local\Temp\ccXpC7RG.o: In function 'ZN5boost4asio6detail17winsock_init_base7startupERNS2_4dataEhh': D:/Boost/boost_1_51_0/boost/asio/detail/impl/winsock_init.ipp:39: undefined reference to 'WSAStartup@8'C:\Users\oleg\AppData\Local\Temp\ccXpC7RG.o: In function 'ZN5boost4asio6detail17winsock_init_base7cleanupERNS2_4dataE': D:/Boost/boost_1_51_0/boost/asio/detail/impl/winsock_init.ipp:48: undefined reference to 'WSACleanup@0' collect2: ld returned 1 exit status make: *** [stest] Error 1

以下是检查有关上述符号的库的结果(我未能以适当的方式对其进行格式化)

`d:\MinGW\lib>nm -C libws2_32.a | grep WSAStartup
00000000 T WSAStartup@8
00000000 我 imp_WSAStartup@8

d:\MinGW\lib>nm -C libws2_32.a | grep WSACleanup
00000000 T WSACleanup@0
00000000 我 imp_WSACleanup@0

d:\MinGW\lib>nm -C libwsock32.a | grep WSACleanup
00000000 T WSACleanup@0
00000000 我 imp_WSACleanup@0

d:\MinGW\lib>nm -C libwsock32.a | grep WSAStartup
00000000 T WSAStartup@8
00000000 我 imp_WSAStartup@8`

正如我们所见,库中存在符号,并且库位于相应的 -L 命令行选项所引用的位置。
那么,为什么是“未定义的引用”????

【问题讨论】:

    标签: c++ windows mingw wsastartup


    【解决方案1】:

    这是一个非常常见的错误,解决方案非常简单:将链接的库放在源文件和目标文件之后。


    如果对象(或源)文件 A 依赖于库 B,则在链接时 A 必须在命令行上位于 B 之前。这是因为 GNU(可能还有其他)链接器如何解决符号依赖关系。

    如果以相反(和错误)的方式进行操作

    g++ -lB A.cpp
    

    那么当链接器加载库 B 时,库中的任何函数都没有依赖关系,因此链接器只会丢弃该库。

    所以正确的做法是把库放在最后

    g++ A.cpp -lB
    

    这就是许多示例总是将库last放在命令行的原因。

    所以对于问题的命令行,应该改为

    g++.exe -g -D_WIN32_WINNT=0x0601 -ID:\Boost\boost_1_51_0 \
        -LD:\Boost\boost_1_51_0\stage\lib -LD:\MinGW\lib \
        -o TestSerial.exe TestSerial.cpp \
        -lboost_system-mgw46-d-1_51 -lboost_filesystem-mgw46-d-1_51 -lboost_iostreams-mgw46-d-1_51 -lws2_32 -lwsock32
    

    此顺序对于库间依赖关系也很重要。如果库 L1 依赖于库 L2,那么在命令行中 L1 必须在 L2 之前。

    【讨论】:

    • @OlegG GNU 链接器在 加载要链接的代码之后查找依赖项。因此,如果一个库位于它所使用的目标文件之前(在命令行上),链接器将看到没有对库中任何函数的引用,并忽略该库。
    • 而且,它似乎是特定于 Windows GNU 编译器的。对吗?
    • @OlegG 许多链接器曾经如此,但我真的不知道。为了安全起见,总是将库放在源文件和/或目标文件之后,这也是一种习惯。
    • 我的 GNU/Linux 机器上的 GNU ld 肯定仍然如此。
    • @jaskmar 如果你使用target_link_libraries,那么 CMake 会自动做正确的事情。
    猜你喜欢
    • 2016-03-26
    • 1970-01-01
    • 2011-06-07
    • 1970-01-01
    • 1970-01-01
    • 2015-08-23
    • 2020-02-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多