8

ARM (cortex-m3) 用の GCC4.7.1 クロスツールチェーンをビルドしました。現在、特定の STL クラス (例: ) を確実に使用していない C/C++ コードから実行可能ファイルをリンクしていますstd::string。さらに、例外と RTTI がオフになります。

ただし、ターゲット ELF (たとえば、nm を使用) を見ていると、リンクされているシンボル (明らかに libstdc++ からのもの) がたくさんあります (たとえばstd::exceptionstd::ios_base、 など)。

.textなぜこれが存在するのですか?また、ターゲットのセクション サイズを縮小するために、このようなものを取り除くにはどうすればよいですか?

同僚が、GCC 固有のスタブ関数をオーバーライドするためのヒントを教えてくれました。

namespace __gnu_cxx
{
    void __verbose_terminate_handler()
    {
        for (;;)
            ;
    }
}

これだけで約 20KB のコード サイズが削減されました。
オーバーライドできるスタブは他にもありますか?


更新:
OK、それを修正するときに、私が疑問に思っていたもののほとんどを削除する 1 つの本当にばかげたエラーを見つけまし
#include <iostream>std::cinもちろん、これは static 、インスタンス、std::coutおよびstd::cerrこれらに付随するすべてのものにリンクします。
ステートメントを削除すると、別の 100KB を超える部分に関するセグメントが#include <iostream>縮小されました。.text


それにもかかわらず:私が疑問に思っていることは
まだありますstd::exceptionstd::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> >'

使用するコードサイズは数百バイト程度とそれほど多くないので、無視しても問題ありませんが、これも削除できれば幸いです。

私は明示的に例外を使用していないので、リンク時にこれらがまだインスタンス化されているのはなぜだろうか。実行時に例外を使用するかどうかを実際に決定することはできません?!? 私が今残した名前空間
から唯一残っているのは__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++ を使用しない理由がなくなりました。

4

4 に答える 4

1

クイックフィックス

まず、ターゲットの制限に応じて、上記の @Carl の推奨事項を検討することをお勧めします。私たちは、cortex m3 プラットフォームで C++ を使用しないことを決定しました。

第二に、C または C++ のサイズを縮小するための組み込み開発のヒント - 浮動小数点ライブラリを削除します。多くのアプリケーションでは、固定小数点演算を使用できますが、交渉可能な理由 (「%f」をprintf)。

あなたの同僚が与えたヒントは、おそらくあなたのプラットフォームに非常に固有のものであり、おそらくハードウェアウォッチドッグを持っていますか? そのため、ハードウェア、コード、またはアプリに精通していない他の人がそのようなクイックフィックスの推奨事項を作成することは困難です.

より深く掘り下げる

実際にこれらのライブラリのシンボルを追加しましたか?それが .txt セクションのほとんどを消費する場所ですか?

問題は、必ずしもそのライブラリから何を使用していないかではなく、あなたが何であるかということです。「要求」するライブラリが独自の依存関係を持っている可能性は十分にあります。

これは骨の折れるプロセスです (もっと良い方法があるかもしれません) が、もし私があなただったら、リンクしているライブラリを削除して、実際に何を取り込むかを確認します (STL ヘッダーはこれらのシンボルのいくつかを必要とする場合があります)。そこに驚きがなく、アプリが予想されるライブラリのみをプルする場合は、さらに深く掘り下げる必要があります。

方法 1: - libstdc++ コードを分析する (おそらく長すぎてすぐにジャンプできない)

方法 2: - 私はこれを C++ で行ったことはなく、C ライブラリだけでこれを行ったことがありませんが、理論は成り立つはずです - libstdc++ のリンケージを削除しながら - 一度に 1 つのオブジェクトを libstdc++ から追加します。コードからビルドしてオブジェクト ファイルを使用することができます。明示的に、またはar(ar -tオブジェクトを一覧表示しar -xvて抽出する)などのツールを試して使用することができます。実際に使用しているモジュールがこれらのモジュールを必要とする理由を確認するために分割して征服したい場合は、リンク コマンドを石畳にすることをお勧めしません。1 日の終わりに、ライブラリを再構築できる場合があります。 「なし」フラグのセットで。マニュアルページを読むかar、、、nmobjdump時間がかかりすぎる場合は、おそらくこれの一部を自動化するのに役立つでしょう。私は何年も前にそのようなことをしたので、チートシートが手元にありません。

于 2013-09-16T00:45:15.513 に答える