找出哪个对象/数组使用最多的堆栈内存

Posted

技术标签:

【中文标题】找出哪个对象/数组使用最多的堆栈内存【英文标题】:Finding out which object/array uses most stack memory 【发布时间】:2016-03-19 19:15:30 【问题描述】:

如何找出最贪吃栈内存的数组/对象/等?


注意:以下是问题的原始上下文。从那以后,我意识到我对堆栈的工作方式有严重的误解。

我有一个以段错误结尾的错误程序。段错误是由一个变量突然被无意义的值覆盖造成的……该变量在堆栈内存中。

因此我的理解是,我在程序的某个其他点发生了堆栈内存溢出,这会破坏下一个堆栈内存缓冲区开头的变量值。

但是,valgrind 在遇到段错误之前不会显示任何错误/警告(使用 --leak-checks=yes 启动时)。

因此,一个解决方案是找出哪些对象/数组/等使用了大部分堆栈内存并将它们移动到堆内存。

【问题讨论】:

如果问题是堆栈溢出,那会有所帮助,但这听起来不像这里发生的事情。问题描述表明错误的指针或数组索引超出范围。 如果您使用的是 Mac,则可以使用 Instruments。否则你可以尝试使用Massif 在我看来,这听起来不像是堆栈溢出,而是越界写入数组,覆盖相邻的值,放在堆栈上。 我在被覆盖的变量的内存位置设置了一个观察点(使用 gdb)。事实证明,它在实例化对象时被(非法)访问。所以我怀疑它几乎不可能是由越界数组或错误指针引起的,也许更多是由堆栈溢出引起的......(虽然这不是一个强有力的论点) 如果实例化对象写入越界,则问题出在对象的构造函数中,很可能是指针错误或数组索引越界。 【参考方案1】:

如果您是在 Mac 上开发,那么您可以使用 Instruments,它有一个内存分析器,可以告诉您分配内存的位置并根据它进行聚合。

否则,你可以使用valgrind的Massif工具

如果您使用的是 Mac,则可以使用 Instruments。否则你可以尝试使用Massif。 Massif manual 的示例输出:

--------------------------------------------------------------------------------
  n        time(B)         total(B)   useful-heap(B) extra-heap(B)    stacks(B)
--------------------------------------------------------------------------------
 10         10,080           10,080           10,000            80            0
 11         12,088           12,088           12,000            88            0
 12         16,096           16,096           16,000            96            0
 13         20,104           20,104           20,000           104            0
 14         20,104           20,104           20,000           104            0
99.48% (20,000B) (heap allocation functions) malloc/new/new[], --alloc-fns, etc.
->49.74% (10,000B) 0x804841A: main (example.c:20)
| 
->39.79% (8,000B) 0x80483C2: g (example.c:5)
| ->19.90% (4,000B) 0x80483E2: f (example.c:11)
| | ->19.90% (4,000B) 0x8048431: main (example.c:23)
| |   
| ->19.90% (4,000B) 0x8048436: main (example.c:25)
|   
->09.95% (2,000B) 0x80483DA: f (example.c:10)
  ->09.95% (2,000B) 0x8048431: main (example.c:23)

【讨论】:

【参考方案2】:

尝试使用观察点来查找内存写入时间

【讨论】:

至少在我看来,这应该是一条评论。 @mksteve,我已经尝试过了,但我不认为首先溢出的变量是问题的根源。我相信我的程序中某处有一个变量消耗了太多的堆栈内存但不会直接导致堆栈溢出。相反,它将可用堆栈内存限制到其他变量太少的程度。现在,我如何找到导致问题的变量? @GLorieul 如果可用堆栈内存受到限制,其他变量的剩余空间太少,它们最终会尝试使用比可用堆栈空间更多的堆栈空间,这会导致堆栈溢出,而不是覆盖变量。 @AlgirdasPreidžius 你的意思是堆栈溢出导致程序崩溃而不是覆盖相邻堆栈缓冲区中的变量? @GLorieul 是的,这正是我要说的。而且,相邻堆栈缓冲区是什么意思?您的程序有 堆栈,而不是多个 堆栈缓冲区

以上是关于找出哪个对象/数组使用最多的堆栈内存的主要内容,如果未能解决你的问题,请参考以下文章

初识JVM堆栈

java堆栈的理解

常见的关于堆栈以及list集合的考察方面

Java中堆栈的区别

Java堆栈的区别

2017/02/26学习笔记