细分C++代码大小

Eva*_*ers 11 c++ static-analysis

我正在寻找一个很好的Stack Overflow风格的答案来回答C++代码大小的旧博客中的第一个问题,我将在下面重复:

我真的很喜欢一些工具(理想情况下,基于g ++),它向我展示了编译/链接代码的哪些部分是从C++源代码的哪些部分生成的.例如,要查看特定模板是否正在为数百种不同类型实例化(通过模板特化可修复),或者是否过度内联代码,或者特定函数是否大于预期.

小智 8

如果你想在你的C++代码中找到代码膨胀的来源,那我就用'nm'.以下命令将列出应用中具有最大代码和数据块的所有符号:

nm --demangle --print-size --size-sort --reverse-sort <executable_or_lib_name> | less
Run Code Online (Sandbox Code Playgroud)


nat*_*ose 5

看起来像这样的东西应该存在,但我没有使用过类似的东西.不过,我可以告诉你我将如何编写这些脚本.有可能更快捷和/或更性感的方式来做到这一点.

首先你可能已经知道的一些东西:

addr2line命令接收一个地址,可以告诉你那里的机器代码实现的源代码.可执行文件需要使用调试符号构建,并且您可能不希望对它进行太多优化(-O0,-O1或-Os可能与您最初想要的一样高).addr2line有几个标志,你需要阅读它的手册页,但如果你想看到输出中有意义的C++函数名,你肯定需要使用-C或--demangle.

objdump命令可以在许多类型的目标文件中打印出有关这些东西的各种有趣的东西.它可以做的一件事就是打印出一个表,该表表示目标文件中的符号或由目标文件引用的符号(包括可执行文件).

现在,您想要做什么:

你想要的是objdump告诉你.text部分的地址和大小.这是实际的可执行机器代码所在的位置.有几种方法可以做到这一点,但最简单的(无论如何)可能是你要做的:

objdump -h my_exe | grep text
Run Code Online (Sandbox Code Playgroud)

这应该导致类似于:

 12  .text       0000049  000000f000  0000000f000 00000400  2**4
Run Code Online (Sandbox Code Playgroud)

如果你没有grep它会给你一个像这样的标题:

Idx  Name        Size     VMA         LMA         File off  Algn
Run Code Online (Sandbox Code Playgroud)

我认为对于可执行文件,VMA和LMA应该是相同的,所以你使用哪个都没关系,但我认为LMA是最好的.你也想要尺寸.

使用LMA和大小,您可以重复调用addr2line,询问机器代码的源代码来源.我不确定如果你传递一个指令内的地址,这将如何工作,但我认为它应该工作.

addr2line -e my_exe <address>
Run Code Online (Sandbox Code Playgroud)

此输出将是路径/文件名,冒号和行号.如果要计算每个唯一路径/文件的出现次数:num,您应该能够查看具有最高计数的那些. Perl使用路径/文件哈希:num作为键,而计数器作为值是一种简单的方法来实现它,但如果你发现运行速度太慢,有更快的方法.您还可以过滤掉您可以确定不需要尽早包含的内容.要显示输出,您可能希望从同一函数中过滤掉不同的行,但您可能会注意到一个函数中的不同行具有不同的计数,这可能很有趣.无论如何,这可以通过让addr2line告诉你函数名称或在第一步中使用objdump -t并一次处理一个函数来完成.

如果您发现某些模板代码或其他代码行在您的可执行文件中出现的次数比您认为的要多,那么您可以轻松找到它们并仔细查看.宏和内联函数可能会显示出与预期不同的最终结果.

如果你不知道,objdump和addr2line来自GNU binutils包,其中包括其他一些有用的工具.