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:
false
thus finishing the program. Memory hasn't been dynamically allocated yet (stays at nullptr
), no problem. calloc
(I know I'm mixing C with C++, wanted to use class and vector
is not available). 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. 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
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.