5

我分析了一些在 Linux 上运行的非常简单的 C++ 程序。所有这些的 main() 的包含成本远不是 100%,大约是 3.83%。我正确使用 callgrind 吗?我在下面粘贴了callgrind_annotatewith的输出。--inclusive=yes

该程序称为堆,它进行简单的堆排序。我使用的命令是

valgrind --tool=callgrind ./heap

然后,我输入

callgrind_annotate --inclusive=yes callgrind.out.25434

输出:

`--------------------------------------------------------------------------------

Profile data file 'callgrind.out.25434' (creator: callgrind-3.6.0)

`--------------------------------------------------------------------------------

I1 cache:
D1 cache:
LL cache:
Timerange: Basic block 0 - 361578
Trigger: Program termination
Profiled target:  ./heap (PID 25434, part 1)
Events recorded:  Ir
Events shown:     Ir
Event sort order: Ir
Thresholds:       99
Include dirs:
User annotated:
Auto-annotation:  off

`--------------------------------------------------------------------------------

       Ir
`--------------------------------------------------------------------------------

2,552,558  PROGRAM TOTALS

`--------------------------------------------------------------------------------

       Ir  file:function

`--------------------------------------------------------------------------------

2,552,558  ???:0x00000810 [/lib/ld-2.7.so]

2,515,793  ???:0x00000a60 [/lib/ld-2.7.so]

2,515,219  ???:0x00015270 [/lib/ld-2.7.so]

2,514,780  ???:0x000021e0 [/lib/ld-2.7.so]

2,456,164  ???:0x0000b2f0 [/lib/ld-2.7.so]

2,256,719  ???:0x00009e40 [/lib/ld-2.7.so]

1,702,371  ???:0x00009ac0 [/lib/ld-2.7.so]

  657,883  ???:0x000098e0 [/lib/ld-2.7.so]

  367,045  ???:0x00017040 [/lib/ld-2.7.so]

   33,170  ???:0x080483e0 [/home/test/heap]

   33,036  ???:0x0000ce60 [/lib/ld-2.7.so]

   31,347  ???:0x0000e850 [/lib/ld-2.7.so]

   30,706  ???:(below main) [/lib/libc-2.7.so]

   30,071  ???:0x00008570 [/lib/ld-2.7.so]

   27,954  ???:0x0000f500 [/lib/ld-2.7.so]

   27,758  ???:0x0000ca30 [/lib/ld-2.7.so]

   21,366  ???:0x0001767b [/lib/ld-2.7.so]
4

1 回答 1

5

main()不是调用图中的顶级函数。glibc 中有一个_start函数,它会调用main()并从main. 还有(对于动态链接的程序 = 几乎所有)一个 ELF 解释器,也称为动态链接器(运行时):/lib/ld-linux.so(这个名称在 linux 中使用,在其他 Unix 中类似于 /lib /ld.so)。链接器将加载和初始化应用程序所需的所有动态库;并且它之前被操作系统调用_start

之前做了什么main?加载库(打开库文件,解析它的头文件,映射它,在内存=重定位处理中采用新位置的代码),以及它们的初始化(动态和静态链接的库都需要这个;注意 glibc=libc 也是库) . 每个库都可能有一个代码,该代码将在加载库(__attribute__((constructor))或全局对象的非平凡构造函数)后立即启动。此外,glibc 可以注册一些在 main 之后运行的函数(例如 via atexit();如果 main 正常返回,它们将被 _start 调用),并且库可能具有全局对象的析构函数。

如果您的程序使用线程,则线程的顶部函数1..n将不是主函数(每个线程都可以分离堆栈;函数调用链main存储在线程 0 的堆栈中)。

在您的示例中,我们看到 /lib/ld-*.so,它是一个动态链接器。似乎,您的应用程序执行时间太短而无法正确分析,并且它使用大量动态库。

于 2011-12-04T04:47:38.027 回答