如何检查使用free []和new []的结果

时间:2011-10-04 12:35:44

标签: c++ memory-management

进程正在与SIGSEV崩溃,并且回溯指示内存损坏。 Valgrind报告表明存在一些“不匹配的空闲”,即分配了new []的内存正在以free()发布。

我找到了以下information from cert.org

  

另一个潜在的问题是,当将指针传递给使用operator new分配给运算符delete()的数组时,有可能在运算符delete()调用free()时(在许多实现中很常见,但不是传递给free()的指针不是通过调用malloc()返回的指针。这是因为malloc()在new new调用时返回的前四个字节通常用于存储数组的大小(同样,不是由Standard指定,而是常见),因此operator new返回的指针实际指向到malloc()返回的指针的四个字节的地址。因此,free()将读取错误的大小以解除分配,这可能导致堆内存损坏问题。

问题是,如何证明free()正在解除错误的大小?任何人都可以建议如何验证在我的环境中发生这种情况,可能使用gdb或任何其他工具?

此外,该数组是基本类型char,因此不存在不调用单独析构函数的问题。

6 个答案:

答案 0 :(得分:4)

  

问题是,如何证明free()正在解除错误的大小?

     

有人可以建议如何在我的环境中验证这种情况,也许使用gdb或任何其他工具?

您已经运行了一个工具,告诉您这就是正在发生的事情。那你为什么要运行另一个工具来验证“这是真的发生了什么”?

根据Valgrind,您与某些free电话不匹配。这是问题,这就是你需要解决的问题。

只要存在该问题,就可能产生一百万种不同的后果,其中一种就是您引用的文字中描述的内容。但是你不需要知道你的程序中实际发生了哪些,因为这些只是症状,你已经知道原因是什么

free / delete不匹配时唯一可以保证的效果是“有些事情发生”。什么“东西”是什么?没有人能说。

除非您故意尝试编写不良软件,否则您应该从源头解决问题,而您所要求的内容对您无法帮助您。

答案 1 :(得分:2)

这是实现定义的。虽然您可能能够使用特定的编译器/工具链/ libc,但您不能一般性地“演示”。

我建议您使用valgrind来发现此类错误。

可以在SO

上找到更全面的此类工具列表

修改以下是推荐帖子,其中包含以下列表: Problem with memory leak check tools in Linux

答案 2 :(得分:1)

您可以尝试使用Duma(http://duma.sourceforge.net/)。它检测malloc / free新/删除不一致。它还在调用free / delete

后检查双重释放和修改内存

答案 3 :(得分:1)

free()的调用不会释放错误的大小,无论您传入的指针是使用malloc()(或其任何变体)分配,还是不是。在第一种情况下,它将解除分配最初分配的数量,而在第二种情况下,它可能会崩溃。

根据实现情况,SIGSEGV附带的错误消息可能会告诉您传入的指针无效(或未分配或类似的东西)。

答案 4 :(得分:0)

如果这是向其他人解释和“证明”这个问题的案例,我建议你解释为什么没有证明它是危险的。在这种情况下,解释应该足以向每个人清楚地显示陷阱。如果您坚持演示,则可以使用malloc创建缓冲区,使用new []创建缓冲区,并显示保存与malloc一起使用的分配大小的内存位置的内容以及使用的内容new。只需观察差异。但是,再次说明这种行为是具体实施的。

答案 5 :(得分:0)

以下是演示此问题的代码示例:

#include <stdlib.h>

struct A
{ int i; };

struct B
{
  ~B(){ }
  int i;
};

int main()
{
  A * a = new A[10];
  free(a);

  B * b = new B[10];
  free(b);
}

如果你在Linux下用ltrace运行它,你会看到类似的东西:

_Znaj(40, 0x293324, 0x292ff4, 0xbfeaca28, 0x165d35) = 0x88f7008
free(0x088f7008)                                 = <void>
_Znaj(44, 0x293324, 0x292ff4, 0xbfeaca28, 0x165d35) = 0x88f7008
free(0x088f700c

所以在第二种情况下,被释放的指针与被分配的指针不匹配(因为用户在B中声明了析构函数)。

当然,new []和free之间的不匹配是未定义的行为,但实际上并不总是会导致SIGSEGV。