在类声明的末尾添加虚函数可避免二进制不兼容? [英] adding virtual function to the end of the class declaration avoids binary incompatibility?

查看:161
本文介绍了在类声明的末尾添加虚函数可避免二进制不兼容?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



如果我有:

  class A 
{
public:
virtual〜A();
virtual void someFuncA()= 0;
virtual void someFuncB()= 0;
virtual void other1()= 0;
private:
int someVal;
};

后来修改这个类的声明为:

  class A 
{
public:
virtual〜A();
virtual void someFuncA()= 0;
virtual void someFuncB()= 0;
virtual void someFuncC()= 0;
virtual void other1()= 0;
private:
int someVal;
};

我从另一个.so上得到一个coredump,它是针对前面的声明编译的。但是如果我在类声明的末尾放置了一些FuncC()(在int someVal之后):

  class A 
{
public:
virtual〜A();
virtual void someFuncA()= 0;
virtual void someFuncB()= 0;
virtual void other1()= 0;
private:
int someVal;
public:
virtual void someFuncC()= 0;
};

我再也看不到coredump了。有人能告诉我这是为什么吗?这个技巧总是有效吗?



PS。编译器是gcc,这是否与其他编译器一起工作?

解决方案

我有点惊讶这个特殊的重新安排有帮助。



您在上面给出的课程通常会被转换为以下顺序的课程:

  typedef void(* vfunc)(void); 

struct __A__impl {
vfunc __vtable_ptr;
int someVal;
};

__A__impl__init(__ A__impl * object){
static vfunc virtual_functions [] = {__A__dtor,__A__someFuncA,__A__sFuncB};
object-> __ vtable__ptr = virtual_functions;

当/如果添加 someFuncC ,你通常应该得到另一个条目添加到类的虚拟功能表。如果编译器安排在其他任何函数之前,你会遇到一个问题,试图调用一个函数实际上调用另一个函数。只要地址位于虚拟函数表的末尾,东西应该仍然可以工作。 C ++并不保证关于如何安排vtables的任何信息(甚至是那些 是一个vtable)。



关于正常数据, (非静态)成员需要按照升序排列,只要没有介入访问指定者( public: protected: 或 private:)。

如果编译器在映射虚拟机时遵循相同的规则函数声明vtable位置,你的第一次尝试应该工作,但你的第二次可能会中断。很显然,这并不能保证 - 只要它始终如一地工作,编译器就可以以任何想要的方式安排vtable。


Could someone explain to me why adding a virtual function to the end of a class declaration avoids binary incompatibility?

If I have:

class A
{ 
  public:
    virtual ~A();
    virtual void someFuncA() = 0;
    virtual void someFuncB() = 0;
    virtual void other1() = 0;
  private:
    int someVal;
};

And later modify this class declaration to:

class A
{ 
  public:
    virtual ~A();
    virtual void someFuncA() = 0;
    virtual void someFuncB() = 0;
    virtual void someFuncC() = 0;
    virtual void other1() = 0;
  private:
    int someVal;
};

I get a coredump from another .so compiled against the previous declaration. But if I put someFuncC() at the end of the class declaration (after "int someVal"):

class A
{ 
  public:
    virtual ~A();
    virtual void someFuncA() = 0;
    virtual void someFuncB() = 0;
    virtual void other1() = 0;
  private:
    int someVal;
  public:
    virtual void someFuncC() = 0;
};

I don't see coredump anymore. Could someone tell me why this is? And does this trick always work?

PS. compiler is gcc, does this work with other compilers?

解决方案

I'm a bit surprised that this particular rearrangement helps at all. It's certainly not guaranteed to work.

The class you give above will normally be translated to something on this order:

typedef void (*vfunc)(void);

struct __A__impl { 
     vfunc __vtable_ptr;
     int someVal;
};

__A__impl__init(__A__impl *object) { 
    static vfunc virtual_functions[] = { __A__dtor, __A__someFuncA, __A__someFuncB};
    object->__vtable__ptr = virtual_functions;    
}

When/if you add someFuncC, you should normally get another entry added to the class' virtual functions table. If the compiler arranges that before any of the other functions, you'll run into a problem where attempting to invoke one function actually invokes another. As long as its address is at the end of the virtual function table, things should still work. C++ doesn't guarantee anything about how vtables are arranged though (or even that there is a vtable).

With respect to normal data, (non-static) members are required to be arranged in ascending order as long as there isn't an intervening access specificer (public:, protected: or private:).

If the compiler followed the same rules when mapping virtual function declarations to vtable positions, your first attempt should work, but your second could break. Obviously enough, there's no guarantee of that though -- as long as it works consistently, the compiler can arrange the vtable about any way it wants to.

这篇关于在类声明的末尾添加虚函数可避免二进制不兼容?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆