【问题标题】:Pointer allocated in for: should I have to free it?分配的指针:我应该释放它吗?
【发布时间】:2016-12-06 09:45:14
【问题描述】:

假设我有这个代码:

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

请注意,p 不会在其他任何地方使用,并且每个 for 循环彼此独立。

假设z 没有那么大,那么单个 p 在内存方面并没有那么昂贵。但是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),因为它很耗时?

【问题讨论】:

  • 这里为什么有C++标签?
  • @EdgarRokyan 你是对的。

标签: c memory malloc free


【解决方案1】:

由于您使用 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
}

回答你的问题:

用... free() 它是否正确

是的。如果你用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

【讨论】:

  • 感谢您的回答。我从来没有使用过智能指针,但我的问题是:如果我在std::vector&lt;std::unique_ptr&lt;float[]&gt;&gt; 处使用v 并且在for 循环之外使用v,会发生什么? p 无论如何都会在作用域结束时自动释放?
  • 如果你使用std::vector&lt;std::unique_ptr&lt;float[]&gt;&gt;,你定义了一个堆分配的可调整大小的堆分配数组。您可能想要std::vector&lt;float&gt;。不久前我创建了一个video tutorial on smart pointers - 如果您喜欢通过视频学习,我认为这将是一个不错的起点。
【解决方案2】:

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

如果你不知道z 有多大——我建议在某处写下分配内存的大小,如果z 比它大——那么重新分配,否则——只需重新分配——使用已经分配的内存。

【讨论】:

  • 感谢您的回答。 z 变化很大,可能几百到几十万(这是SIFT算法检测到的关键点的数量,完全取决于输入图像)。
  • 如果 Z 大于先前的高 Z,则只需重新分配内存。
【解决方案3】:

注意:使用了malloc。行为:调用free。就这么简单。可移植、定义明确的代码需要malloc free

分配的内存量在这里不起作用。如果内存过多,malloc 会抛出错误,但这与您始终需要 free 来跟随 malloc 的事实无关。

【讨论】:

  • 感谢您的回答。但是,如果我们谈论的是高性能应用程序,free 可能会很耗时,因此即使内存效率低下,它在时间方面也可能更高效。
  • @justHelloWorld 不要以牺牲正确性为代价来追求效率。如果性能对您很重要,请预先分配内存并重用它,只需as @Starl1ght said。在任何情况下,请在malloc 之后致电free。如果内存量是"highly variable",就像你说的那样,想出一个聪明的方法来做这件事。发现一个模式并想一些鬼鬼祟祟的方法,但不要忘记亲爱的先生free
  • 罗杰先生,我不会忘记他的:D
【解决方案4】:

是的。你必须free它。否则你有内存泄漏,这很糟糕。特别是如果您循环很多次。

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

【讨论】:

    【解决方案5】:

    考虑使用一个可以重复使用的缓冲区,以避免不必要的分配。这可以通过使用std::vector&lt;float&gt; 轻松完成:

    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&lt;float&gt; 最终会自动清理内存。

    【讨论】:

      【解决方案6】:

      似乎大小是恒定的,为什么要一次又一次地分配它? 只需在循环之前分配一次,在循环内部开始初始化。 您可以重复使用内存。并在循环结束后释放内存。

      并且程序在循环之后结束,然后您不必释放它,程序消耗的所有堆内存都将返回给操作系统,但释放您分配的内存始终是一个好习惯。 关于奖金问题,free 不是那么耗时,但分配内存是,所以不用担心 free 所消耗的时间。

      【讨论】:

        【解决方案7】:

        如果您再次重用该内存 - 显然只有在您结束程序并仅分配一次时才释放它更有效(当您需要更大/更小的数组时使用 realloc() 重新分配)。

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

        至于如果你有大量内存并且只关心速度 - 那么显然free()ing 会“减慢”程序,但它所花费的时间非常少,76*(10**-8) 在我的简陋的机器,对于一个 1024 字节的块,所以它是相当微不足道的。

        【讨论】:

          猜你喜欢
          • 2015-05-20
          • 2017-01-09
          • 2010-09-14
          • 1970-01-01
          • 2010-12-25
          • 2015-03-11
          • 2013-11-14
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多