2015-10-27 142 views
1

我有一些代码,我揣摩,为什么我在这里得到一个分段错误:理解为什么会出现一个分段错误

我添加了一个SpeedEffectEffectStack,这工作得很好。但如果我尝试删除其中一个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 
} 
+0

不相关,但它看起来不像'EffectStack'成堆;看起来你更像是使用它。 –

+1

s.removeEffect(&a); // ..如果这个工作,那么它在哪里失败? – basav

+0

也是,m_effects.back()... back()对一个空向量是未定义的行为??检查size()之前你调用back() – basav

回答

0

这可能不会帮助你,但持续的,基于堆栈的地址对象通常不是一个好主意。在上面的代码中,它可能是可以的,因为你知道EffectStack不会超出你的效果。

是否崩溃,如果你这样做仍时有发生:

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

(?,并相应地调整代码的其余部分),这将泄漏过程中的内存,但它会告诉你,如果问题SpeedEffect被销毁。另一种选择是给SpeedEffect一个析构函数(并且影响一个虚拟析构函数)并在里面设置一个断点来查看编译器何时销毁'a'。

+0

这似乎不是一个答案。在发布的代码中,“a”持续时间足够长,以致基于堆栈的问题不应该成为问题。 – JSF

+0

是的..我认为主要的问题是,为什么我可以在测试场景中的效果对象上调用'removeEffect',但是如果我已经将对象传递给了堆栈,则不能。 – Ventu

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 - 有分配无效Test::testStack()内这些对象的内存,但没有明确公布。 在函数的末尾添加这两个语句并重试。

+0

是的,这是正确的,我不删除它们,因为代码中没有删除任何对象。我只尝试从我的“堆栈”中删除地址。我必须在开始时使用这些语句,因为我无法创建一个没有Story和没有Mobility 0bject的Effect对象 – Ventu

0

我发现了这个问题。 我正在使用omnet仿真框架,并且如果我使用TraciMobility,有一些意想不到的事情发生。 没有它,没有错误。

相关问题