堆腐败

时间:2009-07-30 16:43:01

标签: c++ heap corruption

如果我们在新数组和删除char数组之间有大量代码,为什么会出现问题。

Example

void this_is_bad() /* You wouldn't believe how often this kind of code can be found */
{
  char *p = new char[5];    /* spend some cycles in the memory manager */
  /* do some stuff with p */
  delete[] p;      /* spend some more cycles, and create an opportunity for a leak */
}

8 个答案:

答案 0 :(得分:8)

因为有人可能会抛出异常 因为有人可能会增加回报。

如果在new和delete之间有很多代码,你可能不会发现你需要在throw / return之前释放内存吗?

为什么代码中有RAW指针 使用std :: vector。

答案 1 :(得分:5)

您引用的文章指出

 char p[5]; 
在这种情况下,

同样有效,并且没有泄漏的危险。

通常,通过使分配的内存的生命周期非常清晰来避免泄漏,可以看到新内容和删除相关。

两者之间的大的分离更难以检查,并且需要仔细考虑是否有任何方法可以避免删除。

答案 2 :(得分:2)

该代码的链接(和源代码)正在哀叹在该代码中不必要地使用堆。对于恒定且小的内存量,没有理由在堆栈上分配它。

Instead

void this_is_good()
{
   /* Avoid allocation of small temporary objects on the heap*/
   char p[5];    /* Use the stack instead */
   /* do some stuff */
}

原始代码没有任何固有的错误,但它只是不太理想。

答案 3 :(得分:2)

除了关于堆的所有有趣的答案,以及关于新的和删除彼此接近发生之外,我可能会补充说,避免在一个函数中使用大量代码的纯粹事实。如果大量的代码将两行相关的代码分开,那就更糟了。

我会区分“工作量”和“代码量”:

void do_stuff( char* const p );

void formerly_huge_function() {
   char* p = new char[5];
   CoInitialize( NULL );
   do_stuff( p );
   CoUninitialize();
   delete[] p;
}

现在do_stuff可以做很多事情而不会干扰分配问题。但是其他对称的东西也是这样的。

这就是那个要维护代码的人。可能是你,在一个月内。

答案 4 :(得分:1)

该特定示例并未声明在new和delete之间拥有一堆代码必然是坏事;它说如果有办法编写不使用堆的代码,你可能希望更喜欢这样做以避免堆损坏。

这是足够好的建议;如果减少使用堆的数量,则知道堆损坏时的位置。

答案 5 :(得分:0)

我认为在新变量和删除任何变量之间存在大量代码并不是一个问题。使用new的想法是在堆上放置一个值,从而使其保持很长时间。让代码在这些值上执行是一项预期的操作。

当你在新的和删除之间使用相同方法的大量代码时,有什么可以让你陷入麻烦是由于...意外泄漏变量的可能性。

  • 抛出异常
  • 这么长的方法你看不到开头或结尾因此人们从中间开始随意回来而没有意识到他们跳过删除电话

这两个都可以通过使用RAII类型来修复,例如std::vector<char>而不是新/删除对。

答案 6 :(得分:0)

不是,假设“巨大的代码”:

      
  1. 始终运行“delete [] p;”在调用“p = new char [size];”之前或“抛出异常;”
  2.   
  3. 始终运行“p = 0;”在调用“delete [] p;”
  4. 之后

    未能满足第一个条件,将导致p的内容泄露。如果不满足第二个条件,可能会导致双重删除。一般来说,最好使用std :: vector,以避免任何问题。

答案 7 :(得分:-1)

你问这会更好吗?

void this_is_great()
{
   char* p = new char[5];
   delete[] p;
   return;
 }

不是。