【发布时间】:2013-09-18 09:58:54
【问题描述】:
我已经为 ARM (cortex-m3) 构建了 GCC4.7.1 交叉工具链。现在我正在从 C/C++ 代码链接一个可执行文件,该代码肯定不使用某些特定的 STL 类(例如std::string)。此外,异常和 RTTI 被关闭。
虽然当我在寻找目标 ELF(例如使用 nm)时,有很多符号(显然来自 libstdc++)链接在我不希望在那里找到(例如std::exception、std::ios_base、等等)。
为什么会出现这种情况,我怎样才能摆脱这些东西以减少目标的 .text 部分大小?
一位同事给了我一个技巧来覆盖一些 GCC 特定的存根函数:
namespace __gnu_cxx
{
void __verbose_terminate_handler()
{
for (;;)
;
}
}
仅此一项就减少了大约 20KB 的代码大小。
我可以覆盖更多这样的存根吗?
更新:
好的,我发现一个非常愚蠢的错误,在修复它时删除了我想知道的大部分内容:
在其中一个源文件中有一个#include <iostream> 语句(尽管没有从那里调用)。这当然会链接到静态 std::cin、std::cout 和 std::cerr 实例以及随之而来的所有内容。
删除 #include <iostream> 语句将 .text 段减少了大约另一个 > 100KB 的部分。
尽管如此:
我还想知道std::exception 和std::basic_string 的东西:
Namespace summaries:
==============================================================================
Type Size Namespace
T 774 'std'
W 184 'std::string::_Rep'
W 268 'std'
W 472 'std::string'
Class summaries:
==============================================================================
Type Size Class
T 50 'std::error_category'
T 52 'std::type_info'
T 54 'std::bad_exception'
T 54 'std::exception'
T 68 'std::bad_alloc'
T 98 'std::length_error'
T 214 'std::logic_error'
W 268 'std::basic_string<char, std::char_traits<char>, std::allocator<char> >'
实际上并没有使用太多的代码大小,只有大约 100 个字节,所以我可以忽略它,但如果我也能摆脱它,我将不胜感激。
由于我明确地不使用任何异常,我想知道为什么在链接时仍然会实例化这些异常。在运行时无法真正确定是否使用异常?!?
我现在剩下的 __gnu_cxx 命名空间中唯一剩下的是
Type Size Class
T 58 '__gnu_cxx::recursive_init_error'
这是另一个异常类。
终于:
我使用了一些额外的标志来配置 GCC4.7 交叉构建:
--enable-gold=yes
--enable-lto
--enable-cxx-flags='-fno-exceptions -ffunction-sections -fno-omit-frame-pointer'
后面的标志用于编译 libstdc++,与用于构建目标代码的标志基本相同(无论如何这是一个合理的操作)。之后的异常引用(包括__gnu_cxx::recursive_init_error)。
最后一件事是,我在我们的代码库中发现了 std::string 的意外使用。修复后,对std::basic_string<char, std::char_traits<char>, std::allocator<char> > 的引用也消失了。
所以我现在对结果很满意,libstdc++ 不再有不必要的意外开销,没有理由不优先使用 C++。
【问题讨论】:
-
@CarlNorum 对于这个项目,我什至使用 C++11 ;-) ...
-
说真的...如果您的编译器在您的程序中添加了 20k(!) 段纯废话,我强烈建议您更改编译器或将编程语言切换为 C。C++ 语言中没有任何功能可以可以证明这么多无用的开销是合理的。
-
@Lundin 我认为这只是正确调整存根的问题。
-
如果您可以升级到 GCC 4.8,那么使用
--disable-libstdcxx-verbose构建 GCC 会禁用详细终止处理程序,因此您不需要将其存根。使用-fno-rtti(通过--enable-cxx-flags选项)构建libstdc++ 本身将减少库大小。 -
使用
-fno-threadsafe-statics编译将摆脱__recursive_init_error依赖,但如果您使用多个线程,请不要指望一切正常
标签: c++ gcc embedded cross-compiling