了解存在分段错误的原因

时间:2015-10-27 15:54:26

标签: c++ segmentation-fault

我有一些代码,我试着弄清楚,为什么我在这里遇到分段错误:

我向SpeedEffect添加EffectStack,效果非常好。但是如果我尝试删除其中一个Effects(已经在堆栈中),我必须调用effect.removeEffect()。这会导致分段错误。

如果我尝试从effect.removeEffect()函数调用TestStack(),它运行良好(并在控制台上打印预期的“速度效果已删除”)

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
}

StackEffect的实施方式如下:

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
}

3 个答案:

答案 0 :(得分:0)

这可能对你没有帮助,但坚持基于堆栈的对象的地址通常不是一个好主意。在你上面的代码中它可能没问题,因为你知道EffectStack不会比你的效果更长。

如果你这样做,崩溃仍然会发生:

SpeedEffect* a = new SpeedEffect(1.0, st, mob);

(并相应地调整其余的代码?)这当然会泄漏内存,但它会告诉你问题是SpeedEffect被破坏了。另一个选择是给SpeedEffect一个析构函数(和一个虚拟析构函数)并在里面设置一个断点,看看编译器什么时候正在销毁&#39; a&#39;。

答案 1 :(得分:0)

 Story* st = new Story; //<-- only needed for initialization of an Effect
    Veins::TraCIMobility* mob = new Veins::TraCIMobility; //<-- only needed for initialization

我没有看到delete stdelete mob - 在void Test::testStack()中为这些对象分配了内存但未明确释放。 在函数末尾添加这两个语句,然后重试。

答案 2 :(得分:0)

我发现了这个问题。 我正在使用omnet Simulation框架,如果我实现了TraciMobility,就会发生意想不到的事情。 没有它,没有错误..