当使用所有变量时,不是stack'd,malloc'd或(最近)free'd

时间:2014-05-21 18:45:28

标签: c memory-management valgrind

当我调用此函数时:

int within(struct key *node, int *value) {                      
  int length = len(node);                                       
  if ((value <= node[length-1].data) && (value >= node[0].data)) // Problematic line
    return 0;                                                   
  else if (value > node[length-1].data)                         
    return 1;                                                   
  else if (value < node[0].data)                                
    return -1;                                                  
}                                                               

Valgrind引发了此错误消息:

  

地址0x51f60a0不是堆栈&#39; d,malloc&d; d或(最近)免费&#39;

valuenode变量具有正确的值。使用所有变量。那里的内存管理有什么问题?请告诉我,如果代码段没有清除情况。

3 个答案:

答案 0 :(得分:28)

消息Address 0x51f60a0 is not stack'd, malloc'd or (recently) free通常只是更大的Valgrind错误消息的一部分。

这些Valgrind错误消息通常如下所示:

Invalid read of size 4
   at 0x40F6BBCC: (within /usr/lib/libpng.so.2.1.0.9)
   by 0x40F6B804: (within /usr/lib/libpng.so.2.1.0.9)
   by 0x40B07FF4: read_png_image__FP8QImageIO (kernel/qpngio.cpp:326)
   by 0x40AC751B: QImageIO::read() (kernel/qimage.cpp:3621)
   Address 0xBFFFF0E0 is not stack'd, malloc'd or free'd

Invalid read of size 8
   at 0x40060E: free_adj_list (main.c:9)
   by 0x400844: main (main.c:65)
 Address 0x4c1d170 is 16 bytes inside a block of size 24 free'd
   at 0x4A04D72: free (vg_replace_malloc.c:325)
   by 0x400609: free_adj_list (main.c:8)
   by 0x400844: main (main.c:65)

如何阅读这些错误消息

消息的第一部分表明出了什么问题(&#34;无效读取大小4和#34;意味着你试图从你不应该访问的内存地址读取),然后是回溯,其中发生了错误。

回溯后面是您尝试访问的内存地址的详细信息。通过查看地址是否为:

,Valgrind在这里猜测你的意思
  • 就在您有权访问的内存的一部分之外(因此您的程序执行了buffer overrun)。示例消息为Address 0x1002772ac is 4 bytes after a block of size 12 alloc'd
  • 在之前免费的内存块中(所以你的程序used memory after it was freed);例如:Address 0x4c1d170 is 16 bytes inside a block of size 24 free'd

然后这些消息后跟第二个回溯,指示你分配或释放所提到的内存的位置。

但是消息Address 0x51f60a0 is not stack'd, malloc'd or (recently) free'd意味着Valgrind无法猜出你的意图。您尝试访问0x51f60a0处的内存,但该地址最近未被释放,并且不在您已分配的内存的任何其他部分附近。因此,您可以合理地确定此情况下的错误既不是缓冲区溢出也不是免费使用后的错误。

如何调试此类错误

所以我们可以假设0x51f60a0或多或少是&#34;随机&#34;内存地址。我可以想到两个可能的原因:

  • 您取消引用的指针包含一些未初始化的值;在这种情况下,您还应该从Valgrind
  • 收到Use of uninitialised value错误消息
  • 你取消引用一个根本不是指针的值 - 例如。该值实际上可能是程序中某些不相关计算的结果,并且以某种方式将该值写入您稍后使用的指针

除了这些,当然还有可能错误实际上是一些缓冲区溢出或释放后使用,但Valgrind未能检测到它。

如何在程序中调试此错误

我认为缩小问题范围的一种方法是在Valgrind with GDB中启动应用程序以找出确切导致错误的内存访问(node是否错误?是node[length-1]不好吗?node[0]不好吗?)然后首先了解坏的价值是如何产生的。

答案 1 :(得分:2)

您的比较应该是*value <= node[length-1].data
不是value <= node[length-1].data

IOW,你在value变量之前错过了星号。

答案 2 :(得分:0)

我没有回答这个具体问题 一些答案被接受已经有很长一段时间了。但是我想添加导致我的“not stack'd,malloc'd或(最近)free'd”的问题。我希望这对像我这样的搜索引擎所指导的人有用。

就我而言,我分配了一个大小为585的堆数组p。但后来我尝试在733~1300的索引范围内访问p。而valgrind只是表明了这个消息。

ps:如果StackOverflow中这种“答案”不合适,请告诉我。我只想帮忙。