进程正在与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,因此不存在不调用单独析构函数的问题。
答案 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。