2016-12-06 128 views
0

让我们假设我有这样的代码:分配给指针的指针:我是否应该释放它?

for (int i=0;i<n;i++) { 
    //compute z 
    float *p = (float *) malloc (sizeof(float)*z); 
    //do something with p 
} 

注意p不使用其他任何地方和每个for周期独立于其他。

让我们假设z没有那么大,所以p不memmory方面贵。但是,n可能很大,因此p所占用的总内存可能会一致。

是否正确free()它:

for (int i=0;i<n;i++) { 
    //compute z 
    float *p = (float *) malloc (sizeof(float)*z); 
    //do something with p 
    free(p); 
} 

奖金的问题:如果时间的表现将是优先级(而不是内存的消耗),效果会更好,避免free(p),因为它耗时?

+3

为什么C++标签在这里? –

+0

@EdgarRokyan你是对的。 – justHelloWorld

回答

4

既然你这个标记与C++,你不应该使用mallocfree。使用smart pointers(或new/delete,如果您无权访问C++ 11兼容编译器)。与

它是正确的释放(),它...

是:

for (int i=0;i<n;i++) { 
    // compute z 
    std::unique_ptr<float[]> p{new float[z]}; 
    // do something with p 
    // p gets automatically freed at the end of the scope 
} 

回答您的问题。如果你用malloc分配一些东西,你总是需要free它。

会更好地避免免费(p),因为它很耗时?

是的。考虑预先分配循环之外的内存位置。

// preallocate 
std::unique_ptr<float[]> p{new float[z]}; 

for (int i=0;i<n;i++) { 
    // clear p 
    // compute z 
    // do something with p 
} 

// p gets automatically freed at the end of the scope 
+0

感谢您的回答。我从来没有使用智能指针,但我的问题是:如果我'v.push_back(p)''哪里'std :: vector >''和我在外''使用'v' '循环?无论如何,'p'会在范围的最后自动释放? – justHelloWorld

+0

如果你使用'std :: vector >',你正在定义一个堆分配数组的可调整大小的数组。您可能需要'std :: vector '。我前段时间做了一个关于智能指针的视频教程(https://www.youtube.com/watch?v=zMdD-s5_BIY) - 如果您喜欢通过视频学习,我认为这将是一个很好的开始。 –

3

您可以在周期前预先分配必要的内存量并重新使用它。

如果你不知道z有多大 - 我会建议在某处写分配的内存大小,如果z比它大 - 然后重新分配,否则 - 只是重新使用已分配记忆。

+0

感谢您的回答。 'z'是高度可变的,可能只有几百到几十万(这是SIFT算法检测到的关键点的数量,完全取决于输入图像)。 – justHelloWorld

+0

然后只是重新分配,如果Z大于先前的高Z,内存已被分配。 – Starl1ght

0

是的。你必须free吧。否则,你有内存泄漏,这是不好的。特别是如果你循环很多次。

一个很好的经验法则是每malloc必须匹配free。总是。 (这是对规模较大的项目尤其重要)

2

观察:使用malloc。法:援引free。就这么简单。便携式,定义明确的代码需要mallocfree

分配的内存量在这里没有作用。如果内存太多,malloc会抛出一个错误,但这与您始终需要使用free来遵循malloc无关。

+0

感谢您的回答。但是,如果我们谈论高性能应用程序,“免费”可能会耗费大量时间,所以即使内存效率低下,它的时间效率也会更高。 – justHelloWorld

+1

@justHelloWorld不要为了效率而牺牲正确性。如果性能对您很重要,请预先分配内存并重新使用它,只需[如@ Starl1ght所述](http://stackoverflow.com/a/40992293/3494013)。在任何情况下,在'malloc'之后调用'free'。如果内存量是[“高度可变”](http://stackoverflow.com/questions/40992251/pointer-allocated-in-for-should-i-have-to-free-it/40992321#comment69193323_40992293)正如你所说的那样,要想出一个巧妙的方法来做到这一点。找到一个模式,想一些偷偷摸摸的方式,但不要忘记亲爱的先生'免费'。 – Downvoter

+1

罗杰先生,我不会忘记他:D – justHelloWorld

0

考虑使用缓冲区,为避免不必要的分配而重复使用。这可以通过使用std::vector<float>很容易做到:

std::vector<float> p; 
for (int i=0;i<n;i++) { 
    //compute z 
    p.resize(z); 
    //do something with p 
} 

在最坏的情况下,你会得到O(log n)内存分配。使用您的代码,您将获得n内存分配。不调用free()只会导致内存泄漏。 std::vector<float>最终会自动清理内存。

0

看起来大小是不变的,那么为什么你要分配一次又一次呢? 在循环之前只分配一次,循环内初始化。 您可以重新使用内存。循环结束后释放内存。

程序在循环结束后结束,那么您不必释放它,程序消耗的所有堆内存都将返回到操作系统,但释放分配的内存总是一个好习惯。 关于奖励问题,免费并不费时,但分配内存,所以不要担心免费使用的时间。

0

如果您再次使用该内存 - 仅当您结束程序并仅分配一次程序(并且在需要更大/更小的阵列时使用realloc()重新分配),显然更有效。

您可能编程的每个操作系统都会在程序终止时处理释放动态分配的内存。但是,由于我们主要是尽量保持我们的代码尽可能跨平台,所以您应该始终使用动态分配的内存free()

至于如果你有一个巨大的存储量和只顾速度 - 那么显然free() ING会“减慢”的方案,但它需要时间的量是如此之小得可笑,76*(10**-8)我卑微的机器上,对于一个1024字节的块,所以它是相当不重要的。