在从事C ++项目三年后,可执行文件已增长到4 MB。我想看看所有这些空间的去向。有没有一种工具可以报告最大的太空猪是什么?很高兴看到按类(类中的所有函数),模板(所有实例化)和库(多少属于C标准库和STL?exe中的每个库有多少?)的大小。
编辑:注意,我在Windows上使用Visual C ++。
答案 0 :(得分:14)
在Linux 中,您可以使用nm
显示可执行文件中的所有符号,并按大小反向排序:
$ nm -CSr --size-sort <exe>
选项:
-C
demangles C ++名称。-S
显示符号大小。--size-sort
按大小对符号进行排序。-r
撤销排序。如果您想获得每个命名空间或每个类的结果,您只需grep
输出“namespace::
”,“namespace::class_name::
”,等。
如果您只想查看在可执行文件中定义的符号(不是在其他地方定义的符号,如库中),则添加--defined-only
。但是,按大小排序应该注意这一点,因为未定义的符号不会有大小。
对于Windows ,您仍然可以在二进制文件上使用nm
,因为nm
支持COFF二进制文件。你可以通过cygwin安装nm
,或者你可以将windows可执行文件复制到linux盒子并在那里运行nm
。
您还可以尝试dumpbin
,它会在Windows上转储有关二进制文件的信息。您可以使用/SYMBOLS
开关获取有关符号的信息,但看起来它并不直接提供有关其大小的信息。
答案 1 :(得分:7)
在Visual Studio编译的Windows中,此信息位于.map文件中(它将位于.pdb附近)。
ADDED :要将.map文件中找到的修饰名称转换为更易于阅读的内容,可以使用Visual Studio附带的undname.exe实用程序。它接受命令行上的单个名称,或者您可以为它提供.map文件。
例如,
Microsoft (R) C++ Name Undecorator
Copyright (C) Microsoft Corporation. All rights reserved.
Undecoration of "?push_back@?$mini_vector@U?$Point@U?$FixedPoint@$0O@H@Math@@@Math@@$05@@QAAXABU?$Point@U?$FixedPoint@$0O@H@Math@@@Math@@@Z" is
"public: void __cdecl mini_vector<struct Math::Point<struct Math::FixedPoint<14,int> >,6>::push_back(struct Math::Point<struct Math::FixedPoint<14,int> > const &)"
答案 2 :(得分:2)
我无法让nm
为我工作,但确实找到了一个名为Sizer的有用工具。它使用Debug Interface Access库读取Visual Studio创建的调试信息。正如网站上所描述的那样,它非常简单易用。
Sizer.exe <path-to-exe-file>
。输出将转到stdout,因此您可能希望重定向到文件。代码大小在不同的部分细分,按功能,数据,类等分组,每个部分按代码大小的降序排序。
答案 3 :(得分:1)
获取链接地图,或使用dumpbin
获取符号和尺寸列表。
很可能有很多东西被你拉到了你并不严格需要的东西。
补充:你得到了满意的答复吗?我意识到人们可以通过两种方式处理这样的问题:
我个人更喜欢后者 - 它可以更快地获得结果。
你说应用程序是4MB。假设真正必要的大小是1MB(或一些这样的大小)。这意味着如果您从地图文件中随机选择一个例程,那么它可能是您不需要的75%。找出导致它被包含的内容,看看你是否真的需要它。
在您给出的示例中,您看到了一个包装设备无关位图的类。您可以在应用程序中找到该类的实例,并可能用基本的WIN32位图替换它们。它会不那么漂亮,但可以节省应用程序大小。
然后继续这样做。你摆脱的每一件大件都会让剩下的部分占据应用程序的更大比例,因为应用程序已经缩小但是部分却没有。这使得它们更容易在地图文件中找到。
答案 4 :(得分:1)
不要只看代码 - 资源很容易导致数兆字节的增长。