我试图在全局范围内定义一个包含一些动态分配数组的类。当调用类的构造函数时,程序无法访问通过参数文件读取的用户定义的参数(即模拟中的年数),因此它无法将内存分配到适当的大小。我的想法是在类中的私有函数内分配内存,然后使用析构函数释放它。一些示例代码:
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.
}
我从上面的代码片段收到的错误是:
Unhandled exception at 0x5d4e57aa (msvcr100d.dll) in LRGV_SAMPLER.exe: 0xC0000005: Access
violation reading location 0xccccccc0.
这个错误很有意义,因为我在输入析构函数时检查了TransferTracker的内存地址。我的问题是,为什么我们在输入析构函数时会丢失地址?它可能与模拟器是全局的事实有关;如果班级不是全球性的,那么这种范式似乎工作正常。我是面向对象编程的新手,所以感谢任何帮助!
编辑:这基本上是我的错误,并得到答案的帮助。发生了两个问题:(1)指针从未设置为NULL,因此在尝试删除未分配的指针时会产生混淆。 (2)在我的范围内实际上有两个类的实例,这是我的错误。在最终的代码中,只会有一个实例。谢谢大家!答案 0 :(得分:5)
将指针初始化为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;
}
这样你就可以检查它是否已被初始化,如果你想删除它。这是最佳实践,所以总是这样做,而不仅仅是在施工
编辑:
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;
}
}
}
答案 1 :(得分:3)
您必须在构造函数中将实例变量TransferTracker
的值初始化为0
。您遇到的问题是Simulation
类的销毁,而实际上没有为TransferTracker
分配动态内存。
使用空指针在析构函数中调用delete[]
是安全的。问题是,如果您没有为TransferTracker
提供值,则可能会有任何未定义的值,这会导致尝试使用delete[]
解除分配时出现问题。
编辑:
根据您的编辑,您如何确保只有Simulation
类的一个实例?这与您在构建中包含多个.o
文件等有关。
答案 2 :(得分:1)
我怀疑原因是当你没有调用calc()
函数时你的析构函数被调用,因此尚未分配内存。
您希望设置一个“警卫”,以确保您在尝试释放TransferTracker
的内存之前已经分配了内存。