【发布时间】:2015-02-10 23:10:43
【问题描述】:
我有一个非常奇怪且可能很明显的问题,但我似乎找不到错误。我有一个类对象,它包含一个指向另一个类对象的指针,当第一个的解构器被调用时,它会尝试删除它的指针,但会导致段错误而没有进入第二个的解构器。
具体来说,我有一个优化器类的实例:
class Optimizer {
public:
Optimizer();
~Optimizer();
//Lot's of public methods and such
private:
PredictionRenderer *_predictionRenderer;
//Lot's of member variables
};
Optimizer::~Optimizer() {
std::cout<<"optimizer destructor:"<<_predictionRenderer->getWidth()<<std::endl;
delete _predictionRenderer; //THIS LINE CRASHES AND NEVER MAKES IT INTO THE PREDICTION RENDERER DECONSTRUCTOR
//other calls
}
(这是一个大项目,所以为了简洁起见,我删除了所有额外的方法/变量)。
Optimizer 有一个指向 PredictionRenderer 对象的指针,_predictionRenderer。该指针在调用构造函数期间被初始化。该指针是私有的,我检查并确保它不能“退出”(也就是说,此优化器对象之外的任何人都无法获取此指针。它永远不会被任何优化器的方法返回,也永远不会通过优化器方法传递给任何方法)。
当尝试删除 Optimizer 对象时,我的程序在 delete _predictionRenderer 行出现了段错误。执行永远不会进入 PredictionRenderer 解构器。我在delete调用之前的print语句中添加了验证指针不是NULL或者已经被删除,并且调用PredictionRenderer的getWidth方法成功返回,说明一定是一个有效的指针(是否可以调用已删除的对象?)。此外,打印语句只打印一次,所以我很确定优化器对象没有被复制和删除两次。最后,PredictionRenderer 的解构器永远不会被调用,也不会被 delete 或其他任何地方调用。
我不知道是什么原因造成的。有没有人知道发生了什么?
编辑:正如我在 cmets 中提到的,这个代码库很大。我很抱歉没有展示太多,但我无法真正展示所有内容,因为空间不足。这是我正在使用的其他人的代码,据我所知,他实际上从未破坏过这个对象,他只是让它在程序退出时被释放。我也可以这样做,但这似乎是一种黑客行为,不是做生意的好方法。
【问题讨论】:
-
(This is a big project, so for brevity I removed all the extra methods/variables).不。重要的是不要遗漏类的内部信息。原因是我们需要看看你的班级是否遵循“3规则”。 stackoverflow.com/questions/4172722/what-is-the-rule-of-three -
最有可能的是,发生的事情是您正在双重删除,可能是由于不遵循 3 (5) 的规则,并且在没有重新分配的情况下复制指针,所以当您销毁 COPY对象,一切顺利,但是当你去销毁原来的对象时,你又删除了同一个对象。但可能还有很多其他事情,例如覆盖一些缓冲区并因此破坏堆。
-
But the only time this would be a problem is if Optimizer gets copied (which it might),然后停在那里——程序将表现出未定义的行为,无论你多么想合理化为什么没有错误。 -
@Rae_III BTW,正确的术语是
destructor,而不是deconstructor。此外,您的默认构造函数是否将您的指针初始化为(至少)NULL? -
在类中声明一个 private copy-ctor 声明
Optimizer(const Optimizer&);。无需实施(事实上,我们需要你不来实施)。同样对于赋值运算符Optimizer& operator =(const Optimizer&);。两者都应声明为private:且未实现。然后从头开始重新编译。如果它在任何地方破坏了编译,你就会知道没有制作价值副本是大错特错。
标签: c++ pointers segmentation-fault delete-operator