2009-07-30 86 views
1

为什么它是一个问题,如果我们有一个巨大的代码之间新的和删除一个字符数组。堆腐败

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 */ 
} 
+1

我不确定你真的在问什么。在“新”和“删除”之间有大量的代码是没有问题的。不管你有多少代码,堆腐败都很糟糕。 – nos 2009-07-30 16:47:24

+0

这个问题似乎是“给定的代码如何为泄漏创造机会?” – Sean 2009-07-30 16:49:17

+0

我敢打赌,这是一个很快就要到期的家庭作业问题。 – thewillcole 2009-07-30 16:52:01

回答

0

我认为,这不是有新的之间的代码巨额任何变量中删除的问题。使用new的想法是在堆上放置一个值,并因此长时间保持活跃状态​​。让代码在这些值上执行是预期的操作。

什么可以让你陷入困境,当你有一个新的同样的方法中的代码大量和删除是偶然的可变泄漏是由于机会......

  • 引发异常
  • 中的方法得到这么久,你不能看到开始时或结束,因此人们开始随意从中间回来没有意识到他们跳过删除调用

这两个可以通过使用RAII类型,例如固定为std::vector<char>而不是新的/删除对。

+1

通常,我宁愿使用std :: string而不是std :: vector 。 – Brian 2009-07-30 16:51:22

+0

@Brian,当作为一个数组类型对待时,我更喜欢矢量一致性,但不能针对任何RAII类型与手动新/删除进行争辩。 – JaredPar 2009-07-30 16:52:41

5

您引用的文章提出的观点是

char p[5]; 

将只是在这种情况下,有效的,并没有泄漏的危险。

通常,通过使分配的内存的生命周期非常清晰,可以看出新的和删除是相关的,从而避免了泄漏。

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

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

没有什么内在的错误的原代码的,虽然,它只是不再是最理想的。

8

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

如果你在新建和删除之间有很多代码,你可能不会发现你需要在抛出/返回之前释放内存。

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

0

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

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

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

-1

你问这是否会更好?

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

不是。

1

这个特别的例子不是指出有一串代码在新之间并删除必然是坏的;它指出如果有方法可以编写不使用堆的代码,则可能希望避免堆损坏。

这是很体面的建议;如果您减少了使用堆的数量,那么您知道堆损坏时要查看的位置。

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可以做很多事情,而不与分配问题的干扰。但其他对称的东西也是这样。

这是所有关于谁去维护你的代码的人。这可能是你,在一个月内。