单例和ABI稳定性



考虑以下类

// in library 
class A {
public:
static A* instance(){
static A self;
return &self;
}
void foo() { }
private:
A () {}
int a{0};
};

在动态库中定义

然后定义一个带有额外字段b的新版本的类。

class A {
// as before
private:

int b{0};
};

新版本的库是否违反了ABI ?

对于一个普通的类,我会说毫无疑问是,但对于一个单例,我认为它/不是/一个ABI中断(应用程序只处理指向A的指针,没有改变,没有公共改变)。但我不确定,我想要一个明确的答案。

如果应用程序代码需要一个完整类型来编译A,那么是的,这将是一个ABI中断。

如果应用程序仅仅存储一个指向A的指针(并调用库来获取A*),那么就没有ABI中断。

可以与c的FILE*指针进行比较。

A是单例的事实是转移注意力。

是的。

首先,关于标准的保证,更改类定义中的任何单个令牌都需要所有翻译单元(包括库)使用新定义,以不破坏ODR并导致未定义行为。

显然,在实践中存在一些情况,您可以依靠特定于实现的行为来使其工作,而不会在实际意义上破坏ABI。

在您正在显示的情况下,至少instance函数将是一个问题。这个函数是一个内联函数,必须知道A的确切布局。但是,由于它是一个内联函数,因此您无法控制库和库用户使用该函数的相同版本。你可以很容易地得到一个不匹配,然后对象可能被构造成错误的布局。

即使你让instance不是inline,你也会有同样的问题,构造函数也是inline

最新更新