二维数组中的内存泄漏

Posted

技术标签:

【中文标题】二维数组中的内存泄漏【英文标题】: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

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

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

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

编辑:初始化 rowscolumns 成员。将 calloc() 更改为 C++ newdelete

【问题讨论】:

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

顺便说一句,

矢量不可用

你使用的是什么环境?

【讨论】:

如果没有内存泄漏,我应该如何解释valgrind的输出? 等等,等等,等等!你更新的代码使用new会导致内存泄漏!! 它产生了与 calloc 相同的输出。 我认为你需要扩展你的论点,yumetodo。要么我误解了它,要么你基于一个有缺陷的假设。

以上是关于二维数组中的内存泄漏的主要内容,如果未能解决你的问题,请参考以下文章

关于Delphi中二维数组的声明和大小调整(对非基本类型数据,小心内存泄漏)

Objective-C / 数组中的内存泄漏

jdk1.7.0中的内存泄漏

使用 sqlite 的 UIPickerView 中的内存泄漏

从 python 中的共享库返回的数组 - 这是内存泄漏吗?

数组中的高阶函数JS闭包闭包的内存泄漏