【问题标题】:Memory leak in a 2D array二维数组中的内存泄漏
【发布时间】:2017-11-24 02:08:33
【问题描述】:

我有一堂课:

class Land{
public:
  ~Land() { if(map != nullptr) Clean(); }

  bool Create();
  void PrintMap() const;
  void Clean();
private:
  int rows = 0, columns = 0;
  int **map = nullptr;

  bool CorrectDimensions() const;
  void CreateMap();
  bool FillMap();
};
bool Land::Create() {
  //
  printf("Matrix size:\n");
  if(scanf("%d %d", &(this->columns), &(this->rows) ) != 2 || !CorrectDimensions() )
    return false;

  CreateMap();
  printf("Values:\n");
  return FillMap();
}
void Land::CreateMap() {
  //
  this->map = new int*[rows];

  for(int column = 0; column < this->rows; column++)
    map[column] = new int[this->columns];
}
bool Land::FillMap() {
  //
  for(int row = 0; row < this->rows; row++) {
    for(int column = 0; column < this->columns; column++) {
      if( ! scanf("%d", &(this->map[row][column]) ) ) {
        return false;
      }
    }
  }

  return true;
}
void Land::Clean() {
  //
  for(int row = 0; row < this->rows; row++)
  delete [] this->map[row];
  delete [] this->map;
}

还有我的司机:

int main() {
  //
  Land l;

  if( ! l.Create() ) {
    IncorrectInput();
    return 1;
  }

  l.PrintMap(); //prints correct output
}

我想我的程序应该如何工作:

  1. 调用默认构造函数,不需要自定义构造函数。
  2. 检查输入是否满足要求。 如果不是,则返回false,从而完成程序。内存还没有被动态分配(停留在nullptr),没问题。
  3. 如果是,创建一个二维数组使用 calloc(我知道我正在将 C 与 C++ 混合,想使用类,而 vector 不可用)。
  4. 用扫描值填充该二维数组。如果扫描的值不是整数,则返回 false,从而完成程序。
  5. 打印该数组的值。常量函数。
  6. 结束程序,调用析构函数。由于我不知道Create() 是否提前结束(在calloc 之前),我默认将int **map 初始化为nullptr。如果我分配,map 将不再是nullptr 并且需要被释放。否则,析构函数应该是free,这就是Clean() 所做的。
  7. Clean()我遵循动态分配和释放的做法。 calloc 和 free 遵循它们相反的模式。调试确认调用了多少个callocs,调用了多少个frees。

尽管如此,valgrind 仍然报告错误(不是reachable,实际错误)。具体来说:total heap usage: 184 allocs, 23 frees。是什么导致了这个错误,我错过了什么?

编辑:初始化 rows 和 columns 成员。将 calloc() 更改为 C++ new 和 delete。

【问题讨论】:

  • calloc 和 free 在 C++ 中?
  • @John3136 见(I know I'm mixing C with C++, wanted to use class and vector is not available).
  • 不会阻止您使用 new 和 delete
  • 即使您“修复”了问题,您的程序也会以各种方式泄漏内存。如果在创建矩阵的过程中,对calloc 的调用之一失败了怎么办?你将如何恢复那段记忆?
  • 另外,像{Land l; } 这样简单的事情会因为Land 对象中的成员变量未初始化而调用未定义的行为,并且将使用未初始化的rows 和@987654357 调用析构函数@值。

标签: c++ arrays memory-management memory-leaks


【解决方案1】:

没有内存泄漏。 calloc 不会抛出异常。

顺便说一句,在Land::CreateMap 和许多其他地方检测到空指针尊重。 不要忘记检查calloc的返回值

更新

例如,

class foo {
  int* p1;
  int* p2;
  foo()
  {
    p1 = new int;
    p2 = new int;
  }
  ~foo()
  {
    delete p1;
    delete p2;
  }
};
int main()
{
  foo val;
}

在foo的Ctor中,当p2 = new int;抛出异常时,foo的Dtor不会被调用,所以,任何人都可以删除p1!

因此,当您想在 ctor 中使用非 noexcept 运算符 new 分配内存时,您必须使用 RAII 包装器。 C++11 或更高版本有 RAII wapper 类来分配内存,即std::unique_ptr 或std::shared_ptr。

顺便说一句,

矢量不可用

你使用的是什么环境?

【讨论】:

  • 如果没有内存泄漏,我应该如何解释valgrind的输出?
  • 等等,等等,等等!你更新的代码使用new会导致内存泄漏!!
  • 它产生了与 calloc 相同的输出。
  • 我认为你需要扩展你的论点,yumetodo。要么我误解了它,要么你基于一个有缺陷的假设。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-01-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-30
  • 2017-05-26
  • 2021-03-20
相关资源
最近更新 更多