2

我正处于编写相当大的代码的开始阶段。我已经定义了一个类:

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 析构函数。出于某种原因,即使我没有为该指针分配任何内容,atoms != NULL 测试也会返回 true。这是为什么?

编辑:构造函数定义为:

GPUMD::GPUMD() {}
4

2 回答 2

6

因为在构造函数atoms中没有显式初始化NULL或有效指针。将构造函数更改为:

GPUMD::GPUMD() : numAtoms(0), atoms(NULL) {}

请注意,在 ,atoms != NULL之前的检查delete[]是多余的,因为delete[], 或delete, 在NULL指针上是无操作的。以下是安全的:

GPUMD::~GPUMD() {
    delete [] atoms;
}

由于存在动态分配的成员,因此GPUMD您需要防止复制实例GPUMD或实现赋值运算符和复制构造函数(请参阅什么是三规则?)。

作为 C++,考虑使用一个vector<Atom>(或一个vector智能指针)来代替它来为您管理动态内存。

于 2012-10-25T19:31:09.247 回答
1

如果你没有为指针分配任何东西(换句话说,如果你没有初始化它)那么它的值是未定义的。它不是NULL(好吧,这可能是NULL纯粹的机会,但这种机会是微乎其微的。)只有static变量会自动零初始化。

长话短说,NULL在构造函数中将其初始化为:

GPUMD::GPUMD()
: atoms(NULL)
{ }

或者,如果您不喜欢 POD 类型的初始化程序(为什么不呢?),那么:

GPUMD::GPUMD()
{ atoms = NULL; }
于 2012-10-25T19:31:53.580 回答