将枚举器添加到枚举中会破坏ABI吗?

时间:2014-12-04 17:45:07

标签: c++ enums abi

特别是,我在库接口中获得了以下代码:

typedef enum
{
    state1,
    state2,
    state3,
    state4,
    state5,
    state_error = -1,
} State;

我严格禁止打破ABI。但是,我想添加state6和state7。它会破坏ABI吗?

我发现了here一些提示,但我有点怀疑它是不是我的情况?

  

你可以......

     
      
  • 将新枚举器附加到现有枚举。
  •   
     

执行:如果这导致编译器为枚举选择更大的底层类型,则会使更改与二进制不兼容。不幸的是,编译器有一些余地可以选择基础类型,因此从API设计的角度来看,建议添加一个具有显式大值的Max ....枚举器(= 255,= 1<< 15,等)创建一个数值枚举器值的区间,保证适合所选的基础类型,无论可能是什么。

3 个答案:

答案 0 :(得分:13)

您的问题是一个很好的例子,为什么长期维持ABI兼容性是一项艰巨的任务。这里问题的核心是兼容性不仅取决于给定的类型,还取决于它在函数/方法原型或复杂类型(例如结构,联合等)中的使用方式。

(1)如果枚举在任何地方用作库的输出(例如返回值或函数填充调用者a.k.a输出参数提供的某些地址),则更改将破坏ABI。将枚举视为合同说"应用程序永远不会看到除列出的那些之外的其他值#34;。添加新的枚举成员会破坏此合同,因为旧的应用程序现在可以看到他们从未计算过的值。

(2)如果枚举被严格地用作库的输入(例如,作为函数/库的行为改变的函数的参数),那么它保持兼容性:你以某种方式改变了契约这永远不会伤害客户,即调用应用程序。旧应用程序永远不会使用新值,并且会获得旧行为,新应用程序只会获得更多选项。

答案 1 :(得分:3)

报价实际上是你的情况。简单地在最后添加新的枚举值(但在state_error之前,因为它具有不同的值)并且它应该是二进制兼容的,除非在您提供的引用中提到,编译器选择使用不同的大小类型,在这么小的枚举的情况下似乎不太可能。

最好的方法是尝试检查:在更改之前和之后执行的简单sizeof(State)应该足够了(尽管您也可能想要检查值是否仍然相同)。

答案 2 :(得分:2)

查看评分最高的枚举器ID:state3为2。

这意味着,即使编译器应该选择char作为基础类型,您也可以在那里轻松容纳100多个额外的枚举器ID,而不会有损坏二进制兼容性的风险。

预先设定用户提供迭代器的值,而不是读取迭代器的值。