GCC和Clang等编译器允许编译没有C ++标准库的C ++程序,例如:使用-nostdlib
命令行标志。似乎这种情况经常无法联系起来,例如:
void f() noexcept { throw 42; }
int main() { f(); }
由于__cxa_allocate_exception
,typeinfo for int
,__cxa_throw
,__gxx_personality_v0
,__clang_call_terminate
,__cxa_begin_catch
,{{等未定义的符号,通常无法链接1}}等等。
即使是简单的
std::terminate()
无法与
链接ld:警告:找不到条目符号
int main() {}
;默认为0000000000400120
并在执行时被操作系统杀死。使用_start
编译器仍会运行显式失败的链接器:
ld:
-c
(mytest
)中的错误;不会创建.eh_frame
表。
在不使用和链接到标准库的情况下编程和编译C ++应用程序或库是否是一个现实的目标?如何在Linux上使用GCC或Clang编译我的代码?没有标准库,哪些核心语言功能无法使用?
答案 0 :(得分:20)
您基本上可以在osdev.org找到所有问题的答案,但无论如何我都会做一个简短的总结。
当你给GCC -nostdlib
时,你说的是#34;没有启动或库文件"。这包括:
crti.o
,crtbegin.o
,crtend.o
和crtn.o
。通常,内核开发人员只关心实现crti.o
和crtend.o
,并通过将crtbegin.o
传递给链接器来让GCC提供crtend.o
和-print-file-name=
。通常,这些只是分别由.init
和.fini
组成的存根,为GCC留出了分别推送crtbegin.o
和crtend.o
内容的空间。这些文件是调用全局构造函数/析构函数所必需的。 libgcc
("low-level runtime library"(-lgcc
),因为即使您通过-nostdlib
GCC也会在您使用时发出对其函数的调用因为看似没有理由导致无法理解的链接错误。即使您正在实施/移植C library,情况也是如此。libstdc++
不,但通常内核开发人员需要它。 Porting a C library然后从头开始实现C ++标准库是一项非常困难的任务。由于您只想摆脱标准库",但保留libc(在Linux系统上),您实际上只使用C库编写C ++。当然,这对你没有任何不妥,你做到了,但最终我不明白这一点,除非你打算开发内核。
必读:
OSDev's C++ page - 如果你真的关心RTTI /异常支持,那就是more annoying to implement than it sounds。通常情况下,人们会通过-fno-rtti
或-fno-exceptions
然后担心这一点或根本不担心。
答案 1 :(得分:5)
"标准"用词不当。在这种情况下,它并不意味着"由C ++标准定义的库(函数集,类等)"但"通常的一组库和对象(以某种格式编译的文件)gcc默认链接"。其中一些是大多数甚至所有程序运行所必需的。
如果您使用此标记,则您有责任提供任何缺失的功能。有几种方法可以这样做: