GCC链接顺序已更改? 我试图用GCC链接一个C++模块,基本上类似于: gcc -c hello.c g++ -c world.cpp gcc -ohello -lstdc++ hello.o world.o gcc -ohello hello.o world.o -lstdc++ 请注意,我使用 -LSTDC++链接C++模块,这样我就可以使用 GCC < /C>而不是 G++< /C>。问题是我得到了一个错误: undefined reference to `operator new(unsigned long)'

GCC链接顺序已更改? 我试图用GCC链接一个C++模块,基本上类似于: gcc -c hello.c g++ -c world.cpp gcc -ohello -lstdc++ hello.o world.o gcc -ohello hello.o world.o -lstdc++ 请注意,我使用 -LSTDC++链接C++模块,这样我就可以使用 GCC < /C>而不是 G++< /C>。问题是我得到了一个错误: undefined reference to `operator new(unsigned long)',gcc,linker,Gcc,Linker,(假设world.cpp至少包含一个对new的调用) 如果我将-lstdc++放在链接器行的末尾,则此错误已修复,如下所示: gcc -c hello.c g++ -c world.cpp gcc -ohello -lstdc++ hello.o world.o gcc -ohello hello.o world.o -lstdc++ 我知道这个问题在这里被问了很多次,但我有一个特殊的要求。我不是直接给GCC打电话。我正在使用另一种编程语言(Mercury)的构建系统,它代表我调用GCC,我

(假设
world.cpp
至少包含一个对
new
的调用)

如果我将
-lstdc++
放在链接器行的末尾,则此错误已修复,如下所示:

gcc -c hello.c
g++ -c world.cpp
gcc -ohello -lstdc++ hello.o world.o
gcc -ohello hello.o world.o -lstdc++
我知道这个问题在这里被问了很多次,但我有一个特殊的要求。我不是直接给GCC打电话。我正在使用另一种编程语言(Mercury)的构建系统,它代表我调用GCC,我无法轻松修改它调用GCC的方式(尽管我可以使用LDFLAGS环境变量指定其他库)。因此,我有两个额外的要求:

  • 我不能使用
    g++
    链接(仅
    gcc
    )——这就是为什么我要使用上面的
    -lstdc++
    技巧,而不是简单地使用
    g++
    链接)
  • 我认为我无法控制链接器命令的顺序——Mercury会将.o文件放在任何库之后的命令行上
我理解订单之所以重要的基本原因,但让我困惑的是,为什么现在就打破了订单?我刚刚更新到Ubuntu 11.10/GCC4.6.1。多年来,我一直在使用上述技术成功地编译这个程序(将
-lstdc++
放在首位)。直到现在才出现这个错误。我的一个无关程序使用
-lgl
与OpenGL链接,当我升级时,它也坏了,我不得不将
-lgl
移动到命令行的末尾。我可能会发现我的许多程序不再编译。为什么会发生这种变化?我的新系统有什么问题吗?还是现在的样子?请注意,这些是普通的共享库,不是静态链接的


我能做些什么使GCC回到旧的方式吗?在旧的方式中,库的顺序无关紧要?是否有其他方法可以说服GCC正确链接
libstdc++
,而不将其移动到命令行上的
.o
文件之后?

如果Mercury将对象文件放在库之后,Mercury将被破坏。库属于对象文件之后-始终。有时,您可能会以相反的顺序逃脱,但这并不可靠。(静态库必须跟踪引用静态库中符号的对象文件。有时,即使没有使用任何符号,链接器也会记录共享库定义的符号;有时,如果共享库至少提供一个符号,链接器只会记录共享库符号。)

因此基本上是这样的“回归”是指在我的整个开发生涯中,我一直依赖于这样一个事实,即它“意外地起作用”,而现在它已经停止工作了?这似乎是一个相当大的变化——在过去十年的大部分时间里,我一直将库放在对象文件之前,因为我不知道这是一个问题:(感谢您的建议。问题似乎不是Mercury将对象放在库之后,而是在我的LDFLAGS命令中存在更复杂的依赖关系。我正在取得进展,因此我将给您打勾。谢谢。未经验证的假设:
ld
中可能有影响您的更改。目标很可能是避免加载。)未使用的共享库。如果使用静态库,则只能获得所需的内容。以前的情况是,如果在链接行上列出共享库,即使库未提供任何符号,也会在运行时加载该库。只有在库满足至少一个符号时加载该库,才能减少程序的启动时间但这也意味着,如果扫描库时唯一突出的符号是
main()
,则不会加载库。请参阅文件中关于
--as needed
版本2.20的
--ld
的注释。另请参阅和
--copy dt needed entries
--no copy dt needed entries
选项。我相信,先前未经验证的假设至少在一定程度上得到了验证。哦,打得不错。我确实去了粗略地看一下gcc和g++collect2调用行之间的差异,我注意到gcc使用了--根据需要,而g++不使用。这也许可以解释它。无论如何,我现在已经解决了它(通过仔细地重新排序LDFLAGS中的依赖项)。非常感谢您对此进行研究。