【问题标题】:Will initialization of static vector using a function give memory leak?使用函数初始化静态向量会导致内存泄漏吗?
【发布时间】:2015-04-17 10:04:38
【问题描述】:

我得到了下面的代码。它编译得很好。

class A
{
public:
  static std::vector<int> vInt;
  static std::vector<int> Foo()
  {
    std::vector<int> tmp;

    // EDIT: in the real application the values
    // inserted in the vector depends on the result
    // of other functions being called before Foo()
    tmp.push_back(7);
    tmp.push_back(9);
    return tmp;
  }
};

std::vector<int> A::vInt;

int main()
{
  // .... some code

  A::vInt = A::Foo();

  // .... more code
}

但我想知道它是否有内存泄漏?

我在想那行:

std::vector<int> A::vInt;

正在构造一个向量(一个空向量)。

但该向量后来被以下行替换:

  A::vInt = A::Foo();

所以第一个向量永远不会被破坏,我有内存泄漏。 这是对还是错?

编辑: 我最初的问题没有提到在实际应用程序中我不能从一开始就调用 Foo() 。 Foo() 返回的值取决于需要首先调用的其他函数。很抱歉不清楚...

【问题讨论】:

  • 无泄漏。赋值运算符为您处理事情。
  • 顺便说一句,您分配的不是初始化。声明和定义确定执行什么初始化,在您的情况下为默认初始化,这意味着为您的示例调用默认ctor。
  • 不,在您的场景中它是无害的(您在运行时更改向量),但如果其他静态对象引用它,则在静态初始化期间可能会变得很麻烦(但是,即使那样,您也没有内存泄漏)

标签: c++ vector memory-leaks


【解决方案1】:

由于您使用的是std::vector,因此没有泄漏。标准库会为您解决这些问题。

【讨论】:

    【解决方案2】:

    通常,除非您使用new 运算符,否则您不必担心泄漏。由于您没有进行动态分配(在堆上),因此不会泄漏任何内容;堆栈上的所有内容都将通过确定性销毁来处理。

    【讨论】:

    • 关于堆栈的注释在这里不适用:static 变量分配在静态存储中,既不在堆栈上,也不在堆上。静态存储在可执行文件中定义,由系统在将程序代码加载到内存时分配。
    【解决方案3】:

    您没有泄漏,但代码在我看来仍然很复杂。我更喜欢这样的:

    #include <vector>
    
    class A
    {
    public:
        static std::vector<int> vInt;
    };
    
    std::vector<int> A::vInt{ 7, 9 };
    
    int main()
    {
        A a;
    }
    

    但一般来说,从函数返回局部向量是完全安全的。

    理论上,编译器编译器复制或移动局部向量到一个临时的,然后销毁局部。然后它将临时文件复制或移动到目的地并销毁临时文件。

    标准明确允许绕过这一点——编译器可以(而且大多数会)将目标的引用传递给函数。函数中的代码将通过该引用直接写入目标,因此根本不会进行复制或移动。

    仍然:在这种情况下,它毫无意义。只需在定义向量的地方初始化向量,就完成了(当然,除非您使用的是不支持此功能的旧编译器,但在这种情况下,最好尽可能更新编译器,而不是编写蹩脚的代码来适应旧的编译器。

    【讨论】:

    • 感谢您的回答和解释。但是,我不能使用建议的解决方案。从一开始我不知道 Foo 会返回什么。这取决于在调用 Foo() 之前调用某些函数的结果。抱歉 - 我的问题并不清楚。我将其添加为编辑。谢谢。
    • 以“理论上,...”开头的段落我翻译成以下伪代码:copy/move tmp to temporary; delete tmp; copy/move temporary to A::vInt; delete temporary; 这听起来很清楚,但我在copy/move temporary to A::vInt; 之前缺少类似delete A:vInt 的东西@ 我知道我在这里错了 :) 但是如何/何时释放原始向量的内存。您可以添加解释吗?谢谢。
    【解决方案4】:

    您的代码不会泄漏。 Foo() 返回的输出将被覆盖在 A:: vInt 的相同地址。 检查下面的 Valgrind 输出,这也表明没有泄漏:

    ==25088== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 4 from 1) ==25088== malloc/free: in use at exit: 0 bytes in 0 blocks. Write failed: Cannot allocate memoryrees, 20 bytes allocated. Amits-MacBook-Pro:~ kamal$ ected errors, rerun with: -v ==25088== All heap blocks were freed -- no leaks are possible.

    【讨论】:

      猜你喜欢
      • 2021-09-16
      • 2019-11-24
      • 1970-01-01
      • 1970-01-01
      • 2010-10-13
      • 1970-01-01
      • 1970-01-01
      • 2011-02-15
      • 2010-11-18
      相关资源
      最近更新 更多