Segfault在初始化对象上调用虚方法

时间:2012-07-14 12:25:19

标签: c++ pointers segmentation-fault

我遇到了一个我不理解的段错误。我正在使用Wt库并用信号做一些奇特的事情(我只提到它,因为它使我能够尝试调试它)。

我从向量中获取指向我的一个小部件的指针,并尝试在它指向的对象上调用方法。 Gdb显示指针解析,如果我检查它指向的对象,它就是我需要修改的对象。在这种情况下,小部件正在向自己广播,因此它被注册为广播者和听众;因此,我还能够验证'broadcaster'指针和'listener'指针是否正在访问同一个对象。他们做到了!

然而,即使我可以看到对象存在,并且被初始化,并且实际上是正确的对象,当我尝试在对象上调用方法时,我得到一个直接的seg错误。我尝试了一些不同的方法(包括一些不修改对象的布尔返回)。我已经尝试通过广播指针和监听器指针调用它们,只是为了尝试调试。

调试器甚至不输入对象;尝试调用方法时会立即发生段错误。

代码!

/* listeners is a vector of pointers to widgets to whom the broadcasting widget
 * is trying to signal.
 */
unsigned int num_listeners = listeners.size();
for (int w = 0; w < num_listeners; w++)
{
    // Moldable is an abstraction of another widget type
    Moldable* widget = listeners.at(w);

    /* Because in this case, the broadcaster and the listener are one in the same, 
     * these two point to the same location in memory; this part works. I know, therefore,
     * that the object has been instantiated, exists, and is happy, or we wouldn't
     * have gotten to this point to begin with. I can also examine the fields with gdb
     * and can verify that all of this is correct.
     */
    Moldable* broadcaster_debug = broadcast->getBroadcaster();

    /* setStyle is a method I created, and have tested in other instances and it
     * works just fine; I've also used native Wt methods for testing this problem and
     * they are also met with segfaults. 
     */
    widget->setStyle(new_style); // segfault goes here!
}

自从研究过将向量存储指针存储起来并不是最好的想法之后我就读过了,我应该研究一下boost :: shared_ptr。可能是这样,我将调查它,但它没有解释为什么在已知存在的对象上调用方法会导致段错误。我想知道为什么会这样。

感谢您的帮助。

编辑: 我已经创建了一个详细的向量操作的要点,因为它比在帖子中更容易适应的代码更多。 https://gist.github.com/3111137

我没有显示创建窗口小部件的代码,因为它是一个递归算法,为了做到这一点,我必须显示整个类决策树来创建窗口小部件。我只想说小部件正在创建;在浏览器中查看应用程序时,我可以在页面上看到它们。一切正常,直到我开始玩我的花哨信号。

Moar编辑: 当我在指令步进模式下查看反汇编时,我可以看到在segfault发生之前,会发生以下操作,其中第一个参数列为'void'。不可否认,我对大会一无所知,这让我很懊恼,但这似乎很重要。任何人都可以解释这条指令的含义以及它是否可能是我的困境的原因?

 add $0x378,%rax //$0x378 is listed as 'void'

另一个编辑: 根据某人的建议,我创建了一个非虚拟方法,我能够在seg故障之前成功调用,这意味着该对象实际上就在那里。如果我采用相同的方法并将其设为虚拟,则会发生seg故障。那么,为什么只有虚方法会产生seg错误呢?

我现在发现,如果在调用类中,我确保指定Moldable :: debug_test(和Moldable :: setStyle),则不会发生seg错误。然而,这似乎与const冒泡有类似的效果 - 每个虚拟方法似乎都想要这个说明符。我以前从未目睹过这种行为。虽然我愿意纠正我的代码,如果这真的是它应该如何,我不确定根本问题是否是别的。

去那儿!

1 个答案:

答案 0 :(得分:0)

好吧,我想通了这个问题,虽然我很伤心地说,这是一个完全错误newbish,由于该项目的性质是超级难找。我会把答案放在这里,而且我也投票决定将这个问题过于局部化。请随意这样做。

BroadcastMessage班级有一个__broadcaster字段(Moldable* __broadcaster;)。当将指向广播器的指针传入BroadcastMessage构造函数时,我忘记将入站指针分配给该字段,这意味着__broadcaster不是Moldable类的完全实现的实例。

因此,有些方法实际上正在工作 - 那些可以内联的方法,或者我为测试创建的虚拟函数(例如,其中一个返回值为1),所以看起来有一个那里的完整物体实际上没有。直到调用一个更专业的方法试图访问segfault发生的对象的某些特定的动态属性。

更重要的是,大多数广播消息的生命周期都在其构造函数中,这意味着它的大多数目的都是在没有问题的情况下实现的,因为广播者可以在构造函数的本地范围内使用。

然而,按照建议使用Valgrind,我确实发现了一些其他潜在问题。我也非常精简并重建了整个项目。我删除了大量不必要的代码,现在作为副作用运行得更快。

无论如何,感谢所有的帮助。对不起,解决方案不仅仅是一个发现。