具有嵌入式结构和虚拟功能的Segfault

时间:2011-01-29 21:40:26

标签: c++ struct virtual

我的结构是这样的:

struct A
{
     int a;
     virtual void do_stuff(A*a)
     {
          cout << "I'm just a boring A-struct: " << a << endl;
     }
}

struct B
{
     A a_part;
     char * bstr;
     void do_stuff(B*bptr)
     {
          cout << "I'm actually a B-struct! See? ..." << bptr->bstr << endl;
     }
}

B * B_new(int n, char * str)
{
     B * b = (B*) malloc(sizeof(struct B));
     b->a_part.a = n;
     b->bstr = strdup(str);
     return b;
}

现在,当我这样做时:

char * blah = strdup("BLAAARGH");
A * b = (A*) B_new(5, blah);
free(blah);
b->do_stuff(b);

当我打电话给do_stuff时,我在最后一行遇到了段错误,我不明白为什么。 这是我第一次在这样的结构中使用虚函数,所以我很丢失。任何帮助将不胜感激!

注意:函数调用必须与参数类型的最后一行格式相同,这就是我不使用类或继承的原因。

3 个答案:

答案 0 :(得分:2)

您将C语言(嵌入式结构)与C ++概念(虚函数)混合在一起。在C ++中,类和继承消除了对嵌入式结构的需求。 virtual函数仅影响同一继承层次结构中的类。在您的情况下,AB之间没有任何关系,因此始终会调用A&#39; s doStuff

您的段错误可能是因为b真的是B,但已分配给A*。当编译器看到b->doStuff时,它会尝试转到vtable以查找要调用的doStuff版本。但是,B没有vtable,因此您的程序崩溃了。

在C ++中,没有从任何其他类继承的虚函数的类的布局与C结构完全相同。

class NormalClass
{
      int a;
      double b;

 public:
      NormalClass(int x, double y);
};

看起来像这样:

+------------------------------------+
| a (4 bytes) | b (8 bytes)          |
+------------------------------------+

但是,具有虚函数的类(或结构)也有一个指向vtable的指针,该指针启用C ++的多态性版本。所以像这样的课程:

 class ClassWithVTable
 {
      int a;
      double b;

   public:
       ClassWithVTable();
       virtual void doSomething();
 };

在内存中列出如下:

  +-----------------------------------------------------------+
  | vptr (sizeof(void *)) | a (4 bytes) | b (8 bytes)         |
  +-----------------------------------------------------------+

vptr指向一个名为vtable的实现定义表,它实际上是一个函数指针数组。

答案 1 :(得分:1)

B *转换为A *,然后尝试通过成员函数调用取消引用它是未定义的行为。一种可能性是seg-fault。我不是说这绝对是原因,但这不是一个好的开始。

我不明白你为什么不在这里使用继承!

答案 2 :(得分:0)

对于多态对象,指向vtable的指针存储在对象内 因此,在运行时,实际调用的方法是通过解除引用并跳转到vtable中找到的 在您的情况下,您将B *投射到A * 由于A是多态的,因此方法调用将通过vtable确定,但由于所使用的对象实际上是B所使用的vpointer,实际上是垃圾并且你得到了段错误。