简体   繁体   中英

Memory leak in a 2D array

I have a class:

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;
}

And my driver:

int main() {
  //
  Land l;

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

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

How I imagine my program should work:

  1. Default constructor gets called, no need for a custom one.
  2. Check if the input satisfies the requirements. If not , return false thus finishing the program. Memory hasn't been dynamically allocated yet (stays at nullptr ), no problem.
  3. If yes, create a 2D array using calloc (I know I'm mixing C with C++, wanted to use class and vector is not available).
  4. Fill that 2D array with scanned values. If scanned values aren't ints, return false, thus finishing the program.
  5. Print the value of that array. Const function.
  6. Finish the program so destructor is called. Since I don't know if Create() ended prematurely (before calloc ) or not, I default initialize int **map to nullptr . If I allocate, map won't be nullptr anymore and will need to be freed. Otherwise, destructor should free , that's what Clean() does.
  7. Clean() I followed the practices of dynamic allocation and freeing. calloc and free follow their reversed patterns. Debugging confirmed that how many calloc s were called, that many free s were called.

With all of this, valgrind still reports errors (not reachable , actual errors). Specifically: total heap usage: 184 allocs, 23 frees . What caused this error, what have I missed?

EDIT: Initialized rows and columns members. Changed calloc() with C++ new and delete .

There is no memory-leak. calloc doesn't throw exception.

BTW, Null-pointer deference is detected in Land::CreateMap and meny other places. Don't forget checking returned value of calloc

updated

For example,

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

In Ctor of foo , when p2 = new int; throw exception, Dtor of foo will not called , so, Anyone can delete p1 !

So, when you want to allocate memory with non-noexcept operator new in ctor, You must use RAII wrapper. C++11 or later has RAII wapper class to allocate memory, that is std::unique_ptr or std::shared_ptr .

BTW,

vector is not available

What's the environment are you using?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM