繁体   English   中英

C ++继承和动态库

[英]C++ Inheritance and dynamic libraries

这个想法如下。 我有一个版本为1的类库,如下所示:

class MY_EXPORT MyClass
{
public:
    virtual void myMethod(int p1);
}

在版本2中,将该类修改为:

class MY_EXPORT MyClass
{
public:
    virtual void myMethod(int p1);
    virtual void myMethod2(int p1, int p2);
}

//implementation of myMethod2 in cpp file
void MyClass::myMethod2(int p1, int p2)
{
    myMethod(p1);
    //...
}

现在,假设用户再次编译了库的版本1,并通过重写myMethod扩展了MyClass 现在,他将库更新为版本2, 而无需重新编译。 让我们进一步假设动态链接器仍成功找到该库并加载它。

问题是,如果我调用方法instance->myMethod2(1, 2); 在库中的某个地方,它可以工作,还是应用程序崩溃? 在这两种情况下,该类都没有成员,因此具有相同的大小。

我认为没有理由猜测该应用程序是否会崩溃,行为是否未定义。 由于库中的ABI发生了更改,因此必须重新编译该应用程序。

当库调用instance->myMethod2(1, 2); 它必须通过在应用程序代码中创建的虚拟表,并假设只有一个虚拟方法: myMethod 从那时起,您将获得未定义的行为。 简而言之,当库ABI更改时,您必须重新编译应用程序。

KDE C ++ ABI准则明确禁止此类更改。 派生类的虚拟表将不包含新方法的地址,因此对派生类的对象的这些方法的虚拟调用将崩溃。

通过更改类的定义而不进行重新编译,就违反了One Definition Rule 未重新编译的用户正在使用旧定义,而您的库正在使用新定义。 这导致未定义的行为。

要了解这可能如何体现,请考虑使用VTable调度函数调用的虚拟函数的典型实现。 库用户已派生一个类,并且此派生类在VTable中仅具有一个功能。 如果将指向此类的指针或引用传递到库中,并且库尝试调用第二个函数,它将尝试访问不存在的VTable条目。 这几乎总是会导致崩溃,尽管对于未定义的行为,无法保证任何事情。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM