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

I15*_*159 9 c valgrind memory-management

当我调用此函数时:

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;                                                  
}                                                               
Run Code Online (Sandbox Code Playgroud)

Valgrind引发了此错误消息:

地址0x51f60a0未堆叠,malloc'd或(最近)free'd

valuenode变量具有正确的值.使用所有变量.那里的内存管理有什么问题?请告诉我,如果片段不清楚情况.

oli*_*ver 31

该消息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
Run Code Online (Sandbox Code Playgroud)

要么

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)
Run Code Online (Sandbox Code Playgroud)

如何阅读这些错误消息

消息的第一部分表示出现了什么问题("无效读取大小4"意味着您尝试从不应访问的内存地址读取),然后是发生错误的回溯.

回溯后面是您尝试访问的内存地址的详细信息.通过查看地址是否为:Valgrind在这里猜测你的意思是什么

  • 就在您可以访问的内存部分之外(因此您的程序执行了缓冲区溢出).示例消息将是Address 0x1002772ac is 4 bytes after a block of size 12 alloc'd
  • 在一块之前被释放的内存块中(所以你的程序在释放后使用了内存); 例: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或多或少是"随机"内存地址.我可以想到两个可能的原因:

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

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

如何在程序中调试此错误

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