2016-10-25 10 views
5

基本的な問題は、ビルドされた実行ファイルのサイズが4GBで、デバッグシンボルをオンにして(デバッグシンボルなしで、 )。どのようにこれらのシンボルがどこから来ているのか、スペースを奪うという点で最大の犯罪者であるかを診断/分析できますか?私は非デバッグの実行可能なサイズを減らすことにいくつかの質問を見つけましたが(しかし、彼らはひどく照らされていません)、ここでは主にデバッグシンボルの乱雑さを減らすことに関心があります。実行ファイルは非常に大きいので、すべてのシンボルをロードするためにgdbにかなりの時間がかかり、デバッグが妨げられています。おそらく、コードの膨らみを減らすことが基本的な作業ですが、私はまず4GBがどこに費やされているか知りたいと思います。 「サイズ--format = SysVの」を介して実行可能ファイルを実行デバッグシンボルのフットプリントの削減(実行ファイルは4GBに膨らんでいます)

私は、次のような出力が得られます。私たちは「debug_strは」〜3.6ギガバイトを取ることを見ることができますね

section     size  addr 
.interp      28 4194872 
.note.ABI-tag    32 4194900 
.note.gnu.build-id   36 4194932 
.gnu.hash    714296 4194968 
.dynsym     2728248 4909264 
.dynstr    13214041 7637512 
.gnu.version    227354 20851554 
.gnu.version_r    528 21078912 
.rela.dyn     37680 21079440 
.rela.plt     15264 21117120 
.init      26 21132384 
.plt      10192 21132416 
.text     25749232 21142608 
.fini       9 46891840 
.rodata     3089441 46891872 
.eh_frame_hdr   584228 49981316 
.eh_frame    2574372 50565544 
.gcc_except_table  1514577 53139916 
.init_array    2152 56753888 
.fini_array     8 56756040 
.jcr       8 56756048 
.data.rel.ro    332264 56756064 
.dynamic     992 57088328 
.got      704 57089320 
.got.plt     5112 57090048 
.data      22720 57095168 
.bss     1317872 57117888 
.comment      44   0 
.debug_aranges   2978704   0 
.debug_info   278337429   0 
.debug_abbrev   1557345   0 
.debug_line   13416850   0 
.debug_str   3620467085   0 
.debug_loc   236168202   0 
.debug_ranges   37473728   0 
Total    4242540803 

いるから。私は100% "debug_str"が何であるか知っているわけではありませんが、それらは文字通りデバッグシンボルの文字列名かもしれないと思いますか?それで、私のシンボルの名前を変更された名前がちょうど光っているほど大きいことを私に伝えていますか?どのようにしてそれらを修正するのですか?

私は何とか「nm」でシンボル名を直接調べることができますが、出力は膨大で、どのように検索するのが最適かわかりません。この種の分析を行うツールはありますか?

コンパイラは 'C++(GCC)4.9.2'でした。そして私は、私がLinux環境で作業していることを言及すべきだと思います。

+0

4Gbはわずか512MBで、おそらく問題はありません。バイナリが4GB〜32Gb以外の場合 –

+0

申し訳ありません。私は4GBを意味します。つまり、 'size'の出力のように〜4e9バイトです。 –

+0

プログラムのリリースバージョンでさえ、非常に大きいです。たぶん、再設計について考えて、複数の(より小さな)モジュールにプログラムを分割するのは時間ですか?複数の実行可能ファイル、または1つの実行可能ファイルと小さな共有ライブラリのセット? –

答えて

1

私が使用するトリックの1つは、実行可能ファイルにstringsを実行することです。これは、長い(おそらくテンプレートによる)と多数の(同じ)デバッグシンボル名を表示します。それをsort | uniq -c | sort -nにパイプして結果を見ることができます。多くの大規模なC++実行ファイルでは、次のようなパターンが表示されます:

my_template<std::basic_string<char, traits, allocator>, std::unordered_map<std::basic_string<char, traits, allocator>, 1L> 
my_template<std::basic_string<char, traits, allocator>, std::unordered_map<std::basic_string<char, traits, allocator>, 2L> 
my_template<std::basic_string<char, traits, allocator>, std::unordered_map<std::basic_string<char, traits, allocator>, 3L> 

私はテンプレートの量を単純に減らすことにしました。時々それは手を抜く。明示的なテンプレートのインスタンス化を使用したり、シンボルをデバッグせずにプロジェクトの特定の部分をコンパイルしたり、dynamic_castまたはtypeidに依存しない場合はRTTIを無効にすることによって、何かを得ることができます。

1

私は何とか直接シンボル名を検査し、「NM」で何かを行うことができますね、しかし出力は膨大であり、私はそれを検索する最善の方法はわかりません。この種の分析を行うツールはありますか?

あなたはシンボル長で、すべてのnmのシンボル出力を注文するには、以下の実行することができます。

nm --no-demangle -a -P --size-sort myexecutable \ 
    | awk '{ print length, $0 }' | sort -n -s | cut -d" " -f2- 

(すべてのためのSort a text file by line length including spacesへの称賛を最初|後に。)これが最後の最長の名前が表示されます。さらに出力をc++filt -tにパイプすると、名前のデマンドが取得され、検索に役立ちます。

状況に応じて、実行ファイルとそのデバッグシンボルを別々のファイルに分割すると便利です。これにより、あまり膨らんでいない実行ファイルをターゲット環境/クライアント/ etcに配布し、デバッグシンボル必要に応じて単一の場所に配置できます。詳細については、How to generate gcc debug symbol outside the build target?を参照してください。

1

私は、主にJohn Zwinck's answerに基づいて、以下を実行することで主な原因を突き止めました。本質的に私は単に実行可能ファイルに "string"を実行し、出力を分析するという提案に従った。

string my_executable > exec_strings.txt 

私は、主にmindriot's methodを次の出力をソート:

cat exec_strings.txt | awk '{ print length, $0 }' | sort -n -s | cut -d" " -f2- > exec_strings_sorted.txt 

と最長の文字列を見ていました。確かに、それは特定のライブラリから、狂ったテンプレートが膨らんでいるように見えました。私は、もう少しのように数えるんでした:そのうちの約1万人が、このライブラリから来ていたように抽出された約300万の文字列のことを見て

cat exec_strings.txt | wc -l 
2928189 
cat exec_strings.txt | grep <culprit_libname> | wc -l 
1108426 

、それはそうです。最後に、それはこれらの百万個の文字列がすべてのスーパー長く、デバッグシンボルごみの偉大な大部分を構成することが明らかになった

cat exec_strings.txt | wc -c 
3659369876 
cat exec_strings.txt | grep <culprit_libname> | wc -c 
3601918899 

を行います。だから少なくとも今は問題の根本を取り除こうとしている間に、この1つのライブラリに集中することができます。

関連する問題