没有标准库的Barebones C++

Barebones C++ without standard library?

本文关键字:Barebones C++ 标准      更新时间:2023-10-16

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

void f() noexcept { throw 42; }
int main() { f(); }

通常由于__cxa_allocate_exceptiontypeinfo for int__cxa_throw__gxx_personality_v0__clang_call_terminate__cxa_begin_catchstd::terminate()等未定义的符号而导致链路失败。

即使是一个简单的

int main() {}

无法与链接

ld:警告:找不到入口符号_start;默认为000000000040120

并且在执行时被OS杀死。使用-c,编译器仍然运行明显失败的链接器:

ld:mytest.eh_frame)错误;则不会创建CCD_ 13表。

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

您基本上会在osdev.org上找到所有问题的答案,但我还是会做一个简短的总结。

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

  • crti.ocrtbegin.ocrtend.ocrtn.o。通常,内核开发人员只关心实现crti.ocrtend.o,并让GCC通过将-print-file-name=传递给链接器来提供crtbegin.ocrtend.o。通常,这些只是分别由.init.fini组成的存根,为GCC分别推送crtbegin.ocrtend.o的内容留出了空间。这些文件是调用全局构造函数/析构函数所必需的
  • 您无法避免链接libgcc("低级运行库"(-lgcc),因为即使您传递-nostdlib,GCC也会在您使用它时发出对其函数的调用,从而导致莫名其妙的链接错误。即使在实现/移植C库时也是如此
  • 你不需要libstdc++,但通常内核开发人员需要它。移植C库然后从头开始实现C++标准库是一项极其困难的任务

既然你只想去掉"标准库",但保留libc(在Linux系统上),那么你本质上就是在用一个C库编程C++。当然,这并没有错,你也可以这样做,但最终我看不出有什么意义,除非你计划开发一个内核。

所需读数:

OSDev的C++页面-如果你真的关心RTTI/异常支持,那么实现起来比听起来更烦人。通常情况下,人们只是通过-fno-rtti-fno-exceptions,然后担心它到底是不是。

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

如果您使用此标志,则您有责任提供任何缺失的功能。有几种方法可以做到这一点:

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