我已经为 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>
语句(尽管没有从那里调用)。这当然会链接到 staticstd::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++ 而不是 C。