【问题标题】:Using only g++ works, but not "g++ -c" and ld仅使用 g++ 有效,但不能使用“g++ -c”和 ld
【发布时间】:2011-10-05 23:53:06
【问题描述】:

我在 main.cpp 中有以下源代码:

#include <iostream>
#include <iomanip>

int main() {
    std::cout << "Hi" << std::endl;
    return 0;
}

使用此命令有效,并创建可执行文件:

g++ -o main main.cpp

但是这个命令不起作用:

g++ -c main.cpp
ld -o main main.o

第二个错误:

ld: warning: cannot find entry symbol _start; defaulting to 00000000004000e8
main.o: In function `main':
main.cpp:(.text+0xa): undefined reference to `std::cout'
main.cpp:(.text+0xf): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)'
main.cpp:(.text+0x14): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::endl<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&)'
main.cpp:(.text+0x1c): undefined reference to `std::ostream::operator<<(std::ostream& (*)(std::ostream&))'
main.o: In function `__static_initialization_and_destruction_0(int, int)':
main.cpp:(.text+0x4a): undefined reference to `std::ios_base::Init::Init()'
main.cpp:(.text+0x4f): undefined reference to `std::ios_base::Init::~Init()'
main.cpp:(.text+0x54): undefined reference to `__dso_handle'
main.cpp:(.text+0x61): undefined reference to `__cxa_atexit'

【问题讨论】:

  • ld 不知道 libstdc++
  • 不要直接调用ld,除非你真的需要。

标签: c++ linker g++


【解决方案1】:

我认为如果您直接使用ld,默认情况下它不包含 C++ 库。您也可以使用g++ 进行链接,它会以正确的设置调用ld

g++ -c main.cpp
g++ -o main main.o

【讨论】:

    【解决方案2】:

    GCC 内部链接了一些额外的库和目标文件。要查看它们是什么,请执行-###,它将打印它将执行的工具命令,包括链接器。我的 GCC 使用的链接器命令是(我在 bold 上创建了我调用 g++ 的实际 .o 文件,因此您可以轻松发现它)。

    /usr/lib/gcc/i686-pc-linux-gnu/4.6.0/collect2 --build-id --eh-frame-hdr -m elf_i386 "--hash-style=both" -dynamic-链接器 /lib/ld-linux.so.2 /usr/lib/gcc/i686-pc-linux-gnu/4.6.0/../../../crt1.o /usr/lib/gcc/i686 -pc-linux-gnu/4.6.0/../../../crti.o /usr/lib/gcc/i686-pc-linux-gnu/4.6.0/crtbegin.o -L/usr/ lib/gcc/i686-pc-linux-gnu/4.6.0 -L/usr/lib/gcc/i686-pc-linux-gnu/4.6.0/../../.. ma​​in1.o "-lstdc++" -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc /usr/lib/gcc/i686-pc-linux-gnu/4.6.0/crtend.o /usr/lib/gcc/i686 -pc-linux-gnu/4.6.0/../../../crtn.o

    您可以用ld 替换collect2 路径(如果我没记错的话,collect2 只需要作为不支持现代二进制格式的 GCC 后端的真实ld 的代理,以 collect 构造函数和析构函数根据它们的错位名称。ELF 格式有本机部分支持)。

    执行该命令,将ld 逐字替换,成功链接可执行文件。

    【讨论】:

      【解决方案3】:

      当您使用g++ 时,它还会链接链接器用来解析名称的libstd++ 库。但是使用g++ -c 然后ld 不会自动链接库。您现在必须手动链接库。

      尝试(未经测试):

      ld -o main main.o -llibstd++
      

      或者您可以通过阅读本手册了解正确的语法:

      【讨论】:

      • 与 libstdc++ 库链接的标志是 -lstdc++
      【解决方案4】:

      嗯,你没有在标准库中链接。 g++ 自动为您执行此操作;这就是我们使用它的原因:它封装了对ccplus1ld 的调用,并处理了所有额外内容。

      顺便说一句,严格来说,g++ main.cpp -o main 的等价物是:

      cc1plus main.cpp -o main.o
      ld -o main main.o
      

      cc1plus 可能不在你的路上;我在/usr/libexec/gcc/i386-redhat-linux/4.1.1/ 找到了我的)

      g++ -c main.cpp 通常会执行第一步。 g++ main.cpp -o main 包含两者。

      g++ 是单个编译和链接工具的包装器,针对 C++ 进行了调整。因此,它为cc1plusld 提供它认为合适的参数,包括在C++ 标准库中链接的参数:

      ld -o main main.o -llibstd++
      

      它还会在运行时链接,可能还有其他一些东西。

      一般来说,这些事情没必要自己去尝试:让g++来处理吧。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-03-14
        • 1970-01-01
        • 2011-11-25
        • 1970-01-01
        • 1970-01-01
        • 2010-09-29
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多