2016-10-25 18 views
5

Таким образом, основная проблема заключается в том, что мой встроенный исполняемый файл имеет размер 4 ГБ с включенными символами отладки (от 75 МБ до 300 МБ без символов отладки и различными уровнями оптимизации). Как я могу диагностировать/анализировать, откуда берутся все эти символы, и которые являются самыми крупными нарушителями с точки зрения занимающих место? Я нашел несколько вопросов по сокращению неиспутимого исполняемого размера (хотя они не были ужасно освещены), но здесь я в основном занимаюсь уменьшением беспорядка символов отладки. Исполняемый файл настолько велик, что требуется большое количество времени для загрузки всех символов, что затрудняет отладку. Возможно, сокращение наворотов кода является основной задачей, но я сначала хотел бы знать, где расходуется мое 4GB.Сокращение отпечатка отладочных символов (исполняемый файл раздувается до 4 ГБ)

Запуск исполняемого файла через «размер --format = SysV» я получаю следующий вывод:

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 

, из которого я предполагаю, что мы можем видеть, что «debug_str» занять ~ 3,6 ГБ. Я не знаю, что такое «debug_str» на 100%, но я предполагаю, что они могут буквально быть строковыми именами символов отладки? Так это говорит мне, что искаженные имена моих символов просто безумно большие? Как я могу выяснить, какие из них и исправить?

Я думаю, что я могу как-то что-то сделать с помощью «nm», непосредственно проверяя имена символов, но результат огромен, и я не уверен, как лучше его искать. Существуют ли какие-либо инструменты для такого анализа?

Используемый компилятор был 'C++ (GCC) 4.9.2'. И я думаю, я должен упомянуть, что я работаю в среде Linux.

+0

4Gb всего лишь 512 МБ и, скорее всего, не вызовет никаких проблем. Если бинарный не 4GB ~ 32Gb –

+0

Извините, да, я имею в виду 4 ГБ. т. е. ~ 4e9 байт, как в выводе «размер» –

+0

Даже версия выпуска вашей программы очень велика. Может быть, пришло время подумать о редизайне и разделить программу на несколько (меньших) модулей? Или несколько исполняемых файлов, или один исполняемый файл, и набор небольших разделяемых библиотек? –

ответ

1

Один трюк, который я использую, заключается в том, чтобы запустить исполняемый файл strings, который напечатает все эти длинные (возможно, из-за шаблонов) и многочисленные (ditto) имена отладочных символов. Вы можете проложить его до 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> 

Вы получаете идею.

В некоторых случаях я решил просто уменьшить количество шаблонов. Иногда он выходит из-под контроля. В других случаях вы можете что-то выиграть, используя явное создание шаблона или компиляцию определенных частей вашего проекта без отладки символов или даже отключение RTTI, если вы не полагаетесь на dynamic_cast или typeid.

1

Я предполагаю, что могу как-то что-то сделать с помощью «nm», непосредственно проверяя имена символов, но результат огромен, и я не уверен, как лучше всего его искать. Существуют ли какие-либо инструменты для такого анализа?

Вы можете выполнить следующую команду, чтобы заказать все выходные nm «s символ длиной символа:

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, чтобы получить демарнированные имена, которые могут помочь вам в поиске.

В зависимости от вашей ситуации было бы полезно разбить исполняемый файл и его символы отладки на отдельные файлы, что позволит вам распределить менее раздутый исполняемый файл в целевые среды/клиенты и т. Д. И сохранить символы отладки в одном месте, если необходимо. Для получения подробной информации см. 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 

и взглянули на самых длинных строк. На самом деле все это выглядело как безумный шаблонный вздутие, из определенной библиотеки. Затем я сделал немного больше подсчитывать, как:

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

видеть, что из приблизительно 3000000 строк, которые извлекаются, похоже, ~ 1 миллиона из них происходили из этой библиотеки. Наконец, делая

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

стало очевидно, что эти миллионы строк все супер долго и составляют большую часть символов отладки мусора. Поэтому по крайней мере сейчас я могу сосредоточиться на этой библиотеке, пытаясь удалить корень проблемы.