C++ &引用;正在尝试释放无效指针“;在析构函数中检测到错误
我正处于编写相当大的代码的开始阶段。我定义了这样一个类:C++ &引用;正在尝试释放无效指针“;在析构函数中检测到错误,c++,C++,我正处于编写相当大的代码的开始阶段。我定义了这样一个类: class GPUMD { private: double xhi, xlo, yhi, ylo, zhi, zlo; int numAtoms; Atom *atoms; public: GPUMD(); ~GPUMD(); }; 析构函数定义如下: GPUMD::~GPUMD() { if(atoms != NULL)
class GPUMD {
private:
double xhi, xlo, yhi, ylo, zhi, zlo;
int numAtoms;
Atom *atoms;
public:
GPUMD();
~GPUMD();
};
析构函数定义如下:
GPUMD::~GPUMD() {
if(atoms != NULL)
delete [] atoms;
}
现在,代码执行以下操作:
int main(int argc, char *argv[]) {
GPUMD gpumd;
exit(0);
}
我收到一个glibc检测到的错误:试图释放无效指针。使用valgrind,我看到这个错误跟踪到我的GPUMD析构函数。由于某种原因,原子!=空测试返回true,即使我没有为该指针分配任何内容。为什么呢
编辑:构造函数定义为:
GPUMD::GPUMD() {}
因为
atoms
未被显式初始化为NULL
或构造函数中的有效指针。将构造函数更改为:
GPUMD::GPUMD() : numAtoms(0), atoms(NULL) {}
请注意,atoms!=由于delete[]
指针上的delete[]
或delete
,在NULL
之前的NULL
检查是多余的。以下是安全的:
GPUMD::~GPUMD() {
delete [] atoms;
}
由于GPUMD
中有一个动态分配的成员,您需要防止复制GPUMD
的实例,或者实现赋值运算符和复制构造函数(请参阅)
作为C++,考虑使用<代码>向量 >(或“代码>向量\代码>”的智能指针),而不是为您管理动态内存。
< P>如果您不给指针分配任何东西(换句话说,如果不初始化它),则其值未定义。它不是NULL
(好吧,它可能是NULL
,完全是偶然的,但这种偶然性很小,几乎没有。)只有静态
变量会自动初始化为零
长话短说,在构造函数中将其初始化为NULL
:
GPUMD::GPUMD()
: atoms(NULL)
{ }
或者,如果您不喜欢POD类型的初始值设定项(为什么不?),那么:
请同时显示构造函数。请注意,在删除之前可以省略与
NULL
的比较,因为删除NULL指针是有效的。无保护的delete[]
通常不是一个好主意,因为指针可能会在其他地方被删除。在这种情况下,如果不明确确保再次将其设置为NULL,这将导致双delete[]
@NikosChantziaras,仅仅因为指针不是NULL
并不保证它指向有效对象,正如这个问题很好地显示的那样。保护删除确实提供了100%的保证,而且NULL
在delete
之后插入指针也不会,因为另一个指针可以指向同一个对象。@hmjd-保护删除确实提供了100%的保证--我想你的意思是“不保证”@NikosChantziaras-除了一个例外,绝对没有理由保护删除。一个例外是,如果您重载了操作符delete
,使其模拟了在第一个C标准之前糟糕的旧时代free
的行为。当时,释放空指针确实造成了各种破坏。这是21世纪。现在需要free
和delete
(sans-override)来允许空指针作为输入,并且在被告知释放/删除空指针时完全不做任何事情。
GPUMD::GPUMD()
{ atoms = NULL; }