Barebones C++没有标准库?

jot*_*tik 15 c++ std

GCC和Clang等编译器允许在没有C++标准库的情况下编译C++程序,例如使用-nostdlib命令行标志.似乎这种情况经常无法与您联系,例如:

void f() noexcept { throw 42; }
int main() { f(); }
Run Code Online (Sandbox Code Playgroud)

通常无法链接由于像未定义的符号__cxa_allocate_exception,typeinfo for int,__cxa_throw,__gxx_personality_v0,__clang_call_terminate,__cxa_begin_catch,std::terminate()等.

即使是简单的

int main() {}
Run Code Online (Sandbox Code Playgroud)

无法链接

ld:警告:找不到输入符号_start; 默认为0000000000400120

并在执行时被操作系统杀死.使用-c编译器仍会运行显式失败的链接器:

LD:错误mytest(.eh_frame); 不会.eh_frame_hdr创建任何表.

在不使用和链接到标准库的情况下编程和编译C++应用程序或库是否是一个现实的目标?如何在Linux上使用GCC或Clang编译我的代码?没有标准库,哪些核心语言功能无法使用?

小智 21

您基本上可以在osdev.org上找到所有问题的答案,但无论如何我都会给出一个简短的总结.

当你给GCC时-nostdlib,你说"没有启动或库文件".这包括:

  • crti.o,crtbegin.o,crtend.ocrtn.o.通常,内核开发人员只关心实现crti.ocrtend.o让GCC提供crtbegin.ocrtend.o传递-print-file-name=给链接器.一般来说,这些都只是存根包括.init.fini分别,留有余地GCC推去的内容crtbegin.o,并crtend.o分别.这些文件是调用全局构造函数/析构函数所必需的.
  • 您无法避免链接libgcc("低级运行时库"(-lgcc),因为即使您通过-nostdlibGCC也会在您使用它时发出对其函数的调用,导致无法理解的链接错误,看似没有理由.即使是你正在实现/移植一个C库.
  • 你并不"需要" libstdc++不,但通常内核开发人员需要它.移植C库然后从头开始实现C++标准库是一项非常困难的任务.

既然你只想摆脱"标准库",但保留libc(在Linux系统上),你实际上只用C库编写C++.当然,这对你没有任何不妥,但你最终我没有看到这一点,除非你打算开发一个内核.

必读:

OSDev的C++页面 - 如果你真的关心RTTI /异常支持,它的实现比听起来更烦人.通常人们只是通过-fno-rtti或者-fno-exceptions然后担心它或者根本不担心.


n. *_* m. 5

"标准"是用词不当.在这种情况下,它并不意味着"C++标准定义的库(函数,类等)",而是"通常的库和对象集合(某种格式的编译文件)gcc默认链接".其中一些是大多数甚至所有程序运行所必需的.

如果您使用此标志,则您有责任提供任何缺少的功能.有几种方法可以这样做:

  1. 从程序中真正需要的Cherry-pick库和对象不在默认集中.(没有多大意义,因为结果很可能与默认链接标志完全相同).
  2. 提供您自己的缺失功能实现.
  3. 通过编译器标志显式禁用程序未使用的语言功能.我知道两个这样的功能:异常和RTTI.这是必需的,因为编译器需要生成与异常相关的代码和RTTI信息,即使这些功能未在此模块中明确使用.