Barebones C ++没有标准库?

时间:2016-05-16 09:01:27

标签: c++ std

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_catch,{{等未定义的符号,通常无法链接1}}等等。

即使是简单的

std::terminate()

无法与

链接
  

ld:警告:找不到条目符号int main() {} ;默认为0000000000400120

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

  

ld:-cmytest)中的错误;不会创建.eh_frame表。

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

2 个答案:

答案 0 :(得分:20)

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

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

  • crti.ocrtbegin.ocrtend.ocrtn.o。通常,内核开发人员只关心实现crti.ocrtend.o,并通过将crtbegin.o传递给链接器来让GCC提供crtend.o-print-file-name=。通常,这些只是分别由.init.fini组成的存根,为GCC留出了分别推送crtbegin.ocrtend.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默认链接"。其中一些是大多数甚至所有程序运行所必需的。

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

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