1

如果我们在 char 数组的 new 和 delete 之间有一大段代码,为什么会出现问题。

例子

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 */
}
4

8 回答 8

8

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

如果你在 new 和 delete 之间有很多代码,你可能没有发现你需要在抛出/返回之前释放内存?

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

于 2009-07-30T16:50:39.660 回答
5

您引用的文章指出

 char p[5]; 

在这种情况下同样有效,并且没有泄漏的危险。

一般来说,你可以通过让分配的内存的生命周期非常清晰来避免泄漏,可以看出新建和删除是相关的。

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

于 2009-07-30T16:50:13.357 回答
2

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

相反

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

不过,原始代码本身并没有什么问题,只是不够理想。

于 2009-07-30T16:50:38.160 回答
2

除了关于堆的所有有趣的答案,以及关于让 new 和 delete 彼此靠近发生的问题之外,我可能会补充一点,要避免在一个函数中包含大量代码的事实。如果大量代码将两行相关的代码分开,那就更糟了。

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

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可以在不干扰分配问题的情况下做很多事情。但其他对称的东西也以这种方式保持在一起。

这一切都与维护您的代码的人有关。可能是你,一个月后。

于 2009-07-30T19:02:52.713 回答
1

该特定示例并没有说明在 new 和 delete 之间有一堆代码一定是不好的;它指出,如果有办法编写不使用堆的代码,您可能更喜欢这种方法以避免堆损坏。

这是足够体面的建议;如果您减少使用堆的数量,那么当堆损坏时,您就知道在哪里查看。

于 2009-07-30T18:45:46.353 回答
0

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

当您在 new 和 delete 之间的同一方法中有大量代码时,可能会给您带来麻烦,因为...

  • 抛出异常
  • 方法太长了,你看不到开头或结尾,因此人们开始从中间任意返回,而没有意识到他们跳过了删除调用

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

于 2009-07-30T16:49:21.610 回答
0

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

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

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

于 2009-07-30T16:51:13.510 回答
-1

你问这样会不会更好?

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

它不是。

于 2009-07-30T16:51:47.037 回答