仅使用 g++有效,但不能“g” -c”和ld

发布于 2024-11-24 01:13:45 字数 1501 浏览 1 评论 0原文

我在 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'

I have the following source code in main.cpp:

#include <iostream>
#include <iomanip>

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

Using this command works, and creates the executable file:

g++ -o main main.cpp

But this commands don't work:

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

The second one errors with:

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'

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

So尛奶瓶 2024-12-01 01:13:45

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

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

I think if you use ld directly it does not include the C++ libraries by default. You can use g++ to do the linking as well, it will call ld with the correct settings.

g++ -c main.cpp
g++ -o main main.o
ぃ弥猫深巷。 2024-12-01 01:13:45

GCC 内部链接了一些额外的库和目标文件。要查看它们是什么,请执行 -###,这将打印它将执行的工具命令,包括链接器。我的 GCC 使用的链接器命令是(我制作了在粗体上调用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/../../.. <强>main1.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

您可以将 collect2 路径替换为 ld< /code> (如果我没记错的话,collect2 仅需要作为不支持现代二进制格式的 GCC 后端的真实 ld 的代理,收集构造函数和析构函数根据其损坏的名称。ELF 格式具有对此的本机部分支持)。

执行该命令并按字面替换 ld 即可成功链接可执行文件。

GCC internally links against a few additional libraries and object files. To see what those are, execute -###, which will print the tool commands it would execute, including the linker. The linker command used by my GCC is (I made the actual .o file I invoked g++ on bold, so you can spot it easily).

/usr/lib/gcc/i686-pc-linux-gnu/4.6.0/collect2 --build-id --eh-frame-hdr -m elf_i386 "--hash-style=both" -dynamic-linker /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/../../.. main1.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

You can substitute the collect2 path by ld (if I remember correctly, collect2 is only needed as a proxy for the real ld by GCC backends that don't support modern binary formats, to collect constructor and destructor functions according to their mangled name. The ELF format has native sections support for that).

Executing that command, with ld substituted literally, successfully links the executable.

稀香 2024-12-01 01:13:45

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

尝试(未经测试):

ld -o main main.o -llibstd++

或者您可以通过阅读本手册来查看正确的语法:

When you use g++, it also links the libstd++ library which linker uses to resolve the names. But using g++ -c and then ld do not link the library automatically. You've to link the library manually now.

Try (untested):

ld -o main main.o -llibstd++

Or you can look into the correct syntax by reading this manual:

苦行僧 2024-12-01 01:13:45

好吧,你没有链接到标准库。 g++ 自动为您完成此操作;这就是我们使用它的原因:它包装了对 ccplus1 和 ld 的调用,并处理了所有额外的内容。

顺便说一句,严格来说,相当于 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++ 来处理它。

Well, you didn't link in the standard library. g++ does this for you automatically; that's why we use it: it wraps calls to ccplus1 and ld with all the extras taken care of.

BTW, strictly speaking, the equivalent of g++ main.cpp -o main is:

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

(cc1plus may well not be on your path; I found mine in /usr/libexec/gcc/i386-redhat-linux/4.1.1/)

g++ -c main.cpp does traditionally perform that first step. g++ main.cpp -o main wraps both.

g++ is a wrapper to the individual compilation and linkage tools, tuned for C++. As such, it provides arguments to cc1plus and ld as it sees fit, including the argument to link in the C++ Standard Library:

ld -o main main.o -llibstd++

It'll also link in the runtime and possibly some other stuff.

In general, there is no need to try to do these things yourself: let g++ take care of it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文