Can one deallocate memory in a destructor if they allocated memory within a private function in C++?
I am trying to define a class in the global scope which contains some dynamically-allocated arrays. When the class' constructor is called, the program does not have access to user-defined parameters read through a parameter file (i.e. the number of years in a simulation) thus it cannot allocate memory to the proper size. My idea was to allocate memory within a private function in the class, and then deallocate it using the destructor. Some example code:
class Simulation{
private:
int initial_call; //a flag used to initialize memory
double *TransferTracker;
public:
Simulation();
~Simulation();
void calc();
};
Simulation simulator; //global instance of Simulation
Simulation::Simulation()
{
initial_call = 1;
}
Simulation::~Simulation()
{
//when calling the destructor, though, the address is
//0xcccccccc and the following attempt to delete produces
//the compiler error.
delete [] TransferTracker; //see error
}
void Simulation::calc()
{
for (int i = 0; i < num_its; i++)
{
if (initial_call)
{
TransferTracker = new double [5];
//The address assigned is, for example, 0x004ce3e0
initial_call = 0;
}
}
//even if this calc function is called multiple times, I see
//that the address is still 0x004ce3e0.
}
The error I receive from the above code fragment is:
Unhandled exception at 0x5d4e57aa (msvcr100d.dll) in LRGV_SAMPLER.exe: 0xC0000005: Access
violation reading location 0xccccccc0.
This error makes sense because I checked the memory address of TransferTracker when entering the destructor. My question is, why do we lose the address when entering the destructor? It probably has something to do with the fact that simulator i开发者_JS百科s global; this paradigm seems to work fine if the class was not global. I am new to object-oriented programming so any help is appreciated!
EDIT: This was basically a blunder on my part and was helped by the answers. Two problems occurred: (1) the pointers were never set to NULL, thus creating confusion on trying to delete unallocated pointers. (2) There were actually two instances of the class in my scope, which was a mistake on my part. In the final code, there will only ever be one instance. Thanks everyone!
Initialize the pointer to NULL (0)
Simulation::Simulation() : TransferTracker(NULL)
{
initial_call = 1;
}
Simulation::~Simulation()
{
//when calling the destructor, though, the address is
//0xcccccccc and the following attempt to delete produces
//the compiler error.
if(TransferTracker) delete [] TransferTracker; //see error
TransferTracker = NULL;
}
That way you can check wether or not it has been initialised when you want to delete it. It's best practice, so do it always, not only at construction
EDIT:
void Simulation::calc()
{
for (int i = 0; i < num_its; i++)
{
if (initial_call)
{
if(TransferTracker) delete [] TransferTracker;
TransferTracker = new double [5];
initial_call = 0;
}
}
}
You have to initialize the value of the instance variable TransferTracker
to 0
in the constructor. The problem you're having is the destruction of the Simulation
class without actually having assigned dynamic memory to TransferTracker
.
Calling delete[]
in the destructor with a null pointer is safe. The problem is that if you don't give a value to TransferTracker
, it may have any undefined value, that will cause trouble trying to deallocate with delete[]
.
EDIT:
As per your edit, how do you assure that there is only one instance of the Simulation
class? This has to do with if you include several .o
files in your build, etc.
I suspect the cause is that your destructor is getting called when you haven't invoked the calc()
function, therefore the memory hasn't been allocated yet.
You want to put in place a "guard" that will make sure that you've already allocated the memory before attempting to deallocate the memory for TransferTracker
.
精彩评论