我有一些代码,我试图找出为什么我在这里遇到段错误:
我将 SpeedEffect
添加到 EffectStack
中,效果很好。但是,如果我尝试删除其中一个 Effects
(已在堆栈中),我必须调用 effect.removeEffect()
。这会导致段错误。
如果我尝试从 TestStack()
函数调用 effect.removeEffect()
,它运行良好(并在控制台上打印出预期的“移除速度效果” )
void Test::testStack() {
Story* st = new Story; //<-- only needed for initialization of an Effect
Veins::TraCIMobility* mob = new Veins::TraCIMobility; //<-- only needed for initialization of an Effect
SpeedEffect a = SpeedEffect(1.0, st, mob);
a.removeEffect(); //<-- This one works quite well
(&a)->removeEffect(); //<-- Clearly, this works too
EffectStack s;
s.addEffect(&a); //<-- Adds a Effect to the effect Stack
assert(s.getEffects().size() == 1);
s.removeEffect(&a); //<-- Try to remove effect from stack
}
Stack
和Effect
实现如下:
class Effect {
public:
Effect(Story* story, Veins::TraCIMobility* car) :
m_story(story), m_car(car) {}
virtual void removeEffect() = 0;
private:
Story* m_story;
protected:
Veins::TraCIMobility* m_car;
};
class SpeedEffect : public Effect {
public:
SpeedEffect(double speed, Story* story, Veins::TraCIMobility* car):
Effect(story, car), m_speed(speed){}
void removeEffect() {
std::cout << "speed effect removed" << std::endl;
}
private:
double m_speed;
};
class EffectStack {
public:
void addEffect(Effect* effect) {
if(std::count(m_effects.begin(), m_effects.end(), effect) == 0) {
m_effects.push_back(effect);
}
}
void removeEffect(Effect* effect) {
if(effect == m_effects.back()) {
//effect is pointing on the same address like its doing before, but causes the seg fault
m_effects.back()->removeEffect(); //<--- Seg Fault here!!
effect->removeEffect(); //<-- if I use this, seg fault too
m_effects.pop_back();
}else {
removeFromMiddle(effect);
}
}
const std::vector<Effect*>& getEffects() {
return m_effects;
}
private:
std::vector<Effect*> m_effects;
};
我希望这段代码足够了,我已经删除了所有未被测试场景调用的函数。
有没有问题,因为speedEffect
a的地址在Stack
中变得无效了?
也许你可以帮我解决这个问题。
对问题的新思考: 不,我测试了更多,这让我更加困惑:
void dofoo(SpeedEffect* ef) {
ef->removeEffect(); //<-- breaks with a segmentation fault
}
void Test::testStack() {
Story* st = new Story;
Veins::TraCIMobility* mob = new Veins::TraCIMobility;
SpeedEffect e = SpeedEffect(3.0, st, mob);
e.removeEffect(); //<-- Works fine
(&e)->removeEffect(); //<-- Works fine also
dofoo(&a); //<-- Jumps into the dofoo() function
}
最佳答案
这可能对您没有帮助,但是持久化基于堆栈的对象的地址通常不是一个好主意。在您上面的代码中,它可能没问题,因为您知道 EffectStack 不会比您的效果长寿。
如果你这样做,崩溃是否仍然发生:
SpeedEffect* a = new SpeedEffect(1.0, st, mob);
(并相应地调整其余代码?)这当然会泄漏内存,但它会告诉您问题是否出在 SpeedEffect 被破坏上。另一种选择是为 SpeedEffect 提供一个析构函数(并为 Effect 提供一个虚拟析构函数)并在内部设置一个断点以查看编译器何时销毁“a”。
关于c++ - 理解为什么会出现段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33372631/