Valgrind 内存泄漏与动态数组 C++

Posted

技术标签:

【中文标题】Valgrind 内存泄漏与动态数组 C++【英文标题】:Valgrind memory leak with dynamic arrays C++ 【发布时间】:2018-01-14 23:42:52 【问题描述】:

我尝试了几种方法来解决这个问题,但似乎无法弄清楚。 Valgrind 用我的 resize 方法指出了内存泄漏,我觉得我可能遗漏了一些简单的东西。

.h 文件

private:
  int* pArray;     // stores math expression
  int currentSize; // size of array

.cpp

void Prog::resize(int newSize)

  cout << "Address of polynomial:\t\t\t" << &pArray << endl;
  int* temp = new int[newSize] 0;
  cout << "Address of temp:\t\t\t" << &temp << endl;
  copy(temp, pArray);
  delete[] pArray;
  pArray = temp;
  cout << "Address of pArray after swap:\t" << &pArray << endl;

  temp = nullptr;

  currentSize = newSize;


void Prog::copy(int* to, int* from)
  
    for (int i = 0; i < currentSize; i++)
      to[i] = from[i];
  

我添加了 cout 以查看地址发生了什么,因为我认为在将 pArray 交换为 temp 后它会打印出 temp 位置的地址,但它似乎保留了其原始位置。这是应该发生的事情吗?

我已经尝试创建一个交换方法,但我使用它时问题仍然存在。

void Prog::swap(int*& to, int*& from) 

  int* temp = to;
  to = from;
  from = temp;
 

这是我从 Valgrind 运行程序时的输出。

程序片段

Address of pArray:                  0000006741EFF218
Address of temp:                    0000006741EFEEE8
Address of pArray after swap:       0000006741EFF218
D = +50x^20000 +15x^11 +5x^10 -12x^7 -4x^6 +30x^5 +4x^4 -2x^3 +50

Valgrind

==22696== 24 bytes in 1 blocks are definitely lost in loss record 1 of 12
==22696==    at 0x4C2E80F: operator new[](unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==22696==    by 0x40230A: Prog::resize(int) (Prog.cpp:332)
==22696==    by 0x401DD7: Prog::operator=(Prog const&) (Prog.cpp:171)
==22696==    by 0x400DEE: main (lab1.cpp:36)
==22696==
==22696== 36 bytes in 1 blocks are definitely lost in loss record 2 of 12
==22696==    at 0x4C2E80F: operator new[](unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==22696==    by 0x40230A: Prog::resize(int) (Prog.cpp:332)
==22696==    by 0x401DD7: Prog::operator=(Prog const&) (Prog.cpp:171)
==22696==    by 0x400DD5: main (lab1.cpp:35)
==22696==
==22696== 52 bytes in 1 blocks are definitely lost in loss record 9 of 12
==22696==    at 0x4C2E80F: operator new[](unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==22696==    by 0x40230A: Prog::resize(int) (Prog.cpp:332)
==22696==    by 0x401DD7: Prog::operator=(Prog const&) (Prog.cpp:171)
==22696==    by 0x40201D: Prog::operator*=(Prog const&) (Prog.cpp:214)
==22696==    by 0x40116D: main (lab1.cpp:55)

感谢任何帮助!

编辑 - 赋值运算符也显示了内存泄漏,但它使用了 resize 方法,这就是我忽略它的原因,但这里请求的其余代码:

Prog::Prog() : currentSize(1)

    pArray = new int[currentSize] 0;


Prog::~Prog()

    for (int i = 0; i < currentSize; i++)
      this->pArray[i] = 0;

    currentSize = 0;

    delete[] pArray;
    pArray = nullptr;



Prog& Prog::operator=(const Prog& rhs)

  if (this == &rhs)
    return *this;

  for (int i = 0; i < currentSize; i++)
    pArray[i] = 0;

  if (this->currentSize < rhs.currentSize)
  
    resize(rhs.currentSize + 1);
    currentSize = rhs.currentSize;
    pArray = new int[currentSize];
    for (int i = 0; i < currentSize; i++)
      pArray[i] = rhs.pArray[i];
  
  else
  
    for (int j = 0; j < rhs.currentSize; j++)
      pArray[j] = rhs.pArray[j];
  

  return *this;

【问题讨论】:

请发布您的构造函数、赋值运算符和析构函数,因为问题可能在于operator= 如何处理返回的数据。 (哦,调查std::shared_ptr 和朋友,因为他们会简化事情) 泄漏在 Prog::operator=(Prog const&) (Prog.cpp:171) 中,您避免发布。 @KenY-N 我添加了其余部分。我目前不允许使用智能指针(虽然我没有看到提到 shared_pointer)。我不能使用 STL 库中的任何东西(带有其大小的向量或数组等) @endanegered -- 你真的应该编写一个复制构造函数Prog::Prog(const Prog&amp;)。然后你的赋值运算符将变成一个使用swap 的三行函数。 除其他问题外,如果newSize &lt; currentSizecopy()Prog::Resize() 中的调用具有未定义的行为。 【参考方案1】:

在您的operator= 中,您调用resize,然后在接下来的两个语句中基本上再次执行相同的操作。由于resize 分配内存(并将该指针存储到pArray,然后你用一个新值覆盖operator= 中的那个值而不释放以前的值,你就会得到泄漏。

【讨论】:

哇...我只是看错了地方,并假设它正在调整大小,因为它在每个块中丢失。谢谢!我正在失去理智,它正盯着我的脸。

以上是关于Valgrind 内存泄漏与动态数组 C++的主要内容,如果未能解决你的问题,请参考以下文章

使用 Valgrind 检测 C++ 内存泄漏

C的内存泄漏检测器?

Valgrind C++ 内存泄漏检测

Valgrind C++ 内存泄漏检测

valgrind--CPP程序内存泄露检查工具

内存泄露检测工具Valgrind