Сломайте размер кода C++

Я ищу хороший ответ стиля переполнения стека на первый вопрос в старом сообщении в блоге Размер кода C++, который я повторю ниже:

Я действительно хотел бы некоторый инструмент (идеально, g ++ базирующийся), который показывает мне, какие части компилировали/связывали код, сгенерированы от какой части исходного кода C++. Например, чтобы видеть, инстанцируют ли конкретный шаблон для сотен различных типов (закрепляемый через шаблонную специализацию) или встраивается ли код чрезмерно, или больше ли конкретные функции, чем ожидалось.

11
задан Peter Mortensen 15 July 2015 в 19:30
поделиться

6 ответов

Кажется, что-то подобное должно существовать, но я не использовал ничего подобного. Однако я могу рассказать вам, как бы я написал это вместе. Вероятно, есть более быстрые и / или сексуальные способы сделать это.

Сначала кое-что, что вы, возможно, уже знаете:

Команда addr2line принимает адрес и может сказать вам, где находится исходный код, который там реализует машинный код. Исполняемый файл должен быть построен с использованием отладочных символов, и вы, вероятно, не захотите сильно его оптимизировать (-O0, -O1 или -Os, вероятно, настолько высоки, насколько вы захотите пойти в любом случае).addr2line имеет несколько флагов, и вы захотите прочитать его справочную страницу, но вам обязательно нужно использовать -C или --demangle, если вы хотите видеть имена функций C ++, которые имеют смысл в выводе.

Команда objdump может распечатывать всевозможные интересные вещи о материалах многих типов объектных файлов. Одна из вещей, которую он может сделать, - это распечатать таблицу, представляющую символы в объектном файле или упомянутые в нем (включая исполняемые файлы).

Теперь, что вы хотите с этим сделать:

Вам нужно, чтобы objdump сообщал вам адрес и размер секции .text. Здесь живет настоящий исполняемый машинный код. Есть несколько способов сделать это, но самый простой (во всяком случае для этого), вероятно, для вас:

objdump -h my_exe | grep text

Это должно привести к чему-то вроде:

 12  .text       0000049  000000f000  0000000f000 00000400  2**4

Если вы не использовали grep, он дал бы вам заголовок например:

Idx  Name        Size     VMA         LMA         File off  Algn

Я думаю, что для исполняемых файлов VMA и LMA должны быть одинаковыми, поэтому не имеет значения, что вы используете, но я думаю, что LMA - лучший вариант. Вам также понадобится размер.

С LMA и размером вы можете многократно вызывать addr2line, запрашивая источник исходного кода машинного кода. Я не уверен, как это будет работать, если вы передадите адрес, который был в одной инструкции, но я думаю, что это должно сработать.

addr2line -e my_exe <address>

Результатом будет путь / имя файла, двоеточие и номер строки. Если вы должны подсчитать количество вхождений каждого уникального пути / файла: num, вы сможете посмотреть на те, которые имеют наибольшее количество очков. Perl хэши, использующие путь / файл: num в качестве ключа и счетчик в качестве значения, были бы простым способом реализовать это, хотя есть более быстрые способы, если вы обнаружите, что это работает слишком медленно . Вы также можете отфильтровать вещи, которые, по вашему мнению, не должны быть включены раньше. Для отображения вывода вы можете отфильтровать разные строки из одной и той же функции, но вы можете обратите внимание, что разные строки в одной функции имеют разное количество, что может быть интересно. В любом случае это можно сделать, заставив addr2line сообщать вам имя функции или используя objdump -t на первом шаге и работая по одной функции за раз.

Если вы видите, что какой-то шаблонный код или другие строки кода появляются в ваших исполняемых файлах чаще, чем вы думаете, то вы можете легко найти их и внимательно изучить. Макросы и встроенные функции могут проявить себя иначе, чем вы ожидаете.

Если вы не знали, objdump и addr2line взяты из пакета GNU binutils , который включает несколько других полезных инструментов.

5
ответ дан 3 December 2019 в 06:20
поделиться

Не знаю, поможет ли это, но есть флаг gcc для записи кода сборки, который он генерирует, в текстовый файл для вашего исследования.

" -S Используется вместо -c для создания исходного файла ассемблера с использованием .s в качестве расширения вместо объектного файла. Это может быть полезно, если вам нужно изучить сгенерированный ассемблерный код. "

1
ответ дан 3 December 2019 в 06:20
поделиться

В Visual C++ для этого, по сути, и предназначены файлы .PDB.

0
ответ дан 3 December 2019 в 06:20
поделиться

Если вы хотите найти источники раздутого кода в вашем коде C ++, я использовал для этого 'nm'. Следующая команда выведет список всех символов в вашем приложении с самым большим кодом и фрагментами данных вверху:

nm --demangle --print-size --size-sort --reverse-sort <executable_or_lib_name> | less
8
ответ дан 3 December 2019 в 06:20
поделиться

В большинстве компиляторов C есть способ генерации файла .map. В этом файле перечислены все скомпилированные библиотеки, их адрес и размер. Вы можете использовать этот файл карты, чтобы определить, какие файлы вы должны искать для оптимизации в первую очередь.

1
ответ дан 3 December 2019 в 06:20
поделиться

Я не знаю, как сопоставить код->генерируемую сборку в целом.

Для инстанций шаблонов вы можете использовать что-то вроде "strings -a |grep |sort -u|gc++filt", чтобы получить приблизительное представление о том, что создается.

Два других пункта, которые вы упомянули, кажутся довольно субъективными. Что такое "слишком много" инлайнинга? Вы беспокоитесь, что ваш двоичный файл раздувается? Единственное, что там можно сделать, это зайти в gdb и разобрать вызывающую функцию, чтобы посмотреть, что она генерирует, а проверить "чрезмерную" инкрустацию в целом нечем.

Что касается размера функции, мне снова интересно, почему это имеет значение? Вы пытаетесь найти код, который неожиданно расширяется при компиляции? Как вы вообще определяете ожидаемый размер, чтобы инструмент мог его исследовать? Опять же, вы всегда можете разобрать любую функцию, которая, как вы подозреваете, компилируется в гораздо больший код, чем вам нужно, и посмотреть, что именно делает компилятор.

0
ответ дан 3 December 2019 в 06:20
поделиться
Другие вопросы по тегам:

Похожие вопросы: