在 Unix 中的 C 中分析每个函数的内存使用情况

Profile per-function memory usage in C in Unix

在 Unix 中,有什么方法可以获得用 C 编写的程序的每个函数的总内存使用量?也就是说,包括在该函数中声明的局部变量(堆栈)、malloc 变量(堆)和静态变量(bss 和数据)。

我知道 Valgrind 的 Massif 可以检索堆上的信息,但其他两个呢?

正如 OP 强调的那样,每个 class 存储空间都可以使用不同的工具进行测量。在 old 天 (C90),这相对简单。如今,复杂得多...

静态内存:

静态内存(静态或全局),可以使用 size 工具在目标文件级别 (.o) 测量。这将包括文件中所有静态数据的内存——可能是多个函数。例如o5中的函数需要120+512 (data+bss)

size o5.o
   text    data     bss     dec     hex filename
    757     512     120    1389     56d o5.o

自动变量

测量自动变量 ("local") 比较棘手。在 C99 之前,分配在编译时固定(除了 now alloca 调用)。可以检查程序集生成的代码以找出为函数分配了多少堆栈 space。对于允许 VLA 的 C99,这不再可能,例如

void f(int n) {
    int a[n+3] ;   // Variable Length Array, size calculated at run time.
}

此外,通过优化,许多编译器能够检测到两个变量可以共享相同的 space,因为它们不会同时使用。例如,大多数编译器可以判断 x 和 y 可以共享相同的 space.

void f(int n) {

   for (int i=0 ; ... ; ... ) {
       int x[30] ;
   } ;

   for (int j=0 ; ... ; ... ) {
       int y[30] ;
   } ;
}

理论上,可以在 运行 时间内对堆栈大小进行采样,并尝试用 VLA 确定 'typical' 函数的大小。对于没有 VLA 的函数,通常可以从生成的程序集中提取数据。里程会有所不同。

动态变量

对于动态内存分配(malloc 和朋友)- 运行时间工具最好设置为捕获分配了多少内存。然而,大多数工具将无法测量实际的动态使用情况 - 它们通常会在特定时间点对堆进行分析,这可能比函数实际使用的更多或更少。