9

staticメンバー関数を追加することは問題ないことはわかっていますが、enum定義についてはどうでしょうか。新しいデータ メンバーはありません。定義だけです。


少し背景:

文字列表現によってアドレスstaticのバージョン (関数) を認識するメンバー関数を (クラスに)追加する必要があります。IP最初に頭に浮かぶのは、enumforを宣言しIPv4、これを関数の戻りコードにすることです。 IPv6Unknownenum

しかし、バイナリの下位互換性を壊したくありません。

そして、本当に悪い質問 (SO の場合) - ソースや質問はありますか? それについてもっと読むことができますか? つまり、バイナリ互換性を損なうものとそうでないものがあります。それとも、多くのもの (アーキテクチャ、OS、コンパイラなど) に依存しますか?


編集: @PeteKirkham のコメントについて:それでは、少なくとも - 変更されたABIをテスト/チェックする方法はありますか、それについて新しい質問を投稿する方が良いですか?

EDIT2 : SO Question : C++ で ABI ブレークを検出するための静的分析ツールを 見つけました。私はそれが何らかの形でここに関連していると思い、バイナリ互換性をチェックするツールに関する部分に答えます。それが私がここにそれを関連付ける理由です。

4

2 に答える 2

6

ここでの本当の問題は、明らかになぜそれをクラス (静的) メンバーにするのかということです。

定義から明らかなように、これはそれ自体の名前空間 (およびおそらくヘッダー ファイル) 内の完全に自由な関数である可能性があります。または、ソース ファイル内の匿名の名前空間で分離された定義を使用する場合です。

これでも ABI が壊れる可能性はありますが、実際には面白いコンパイラが必要です。

ABIの破損に関して:

  • クラスのサイズを変更する: データ メンバーを追加します。ただし、以前に使用されていないパディングにそれらを隠しておく場合を除きます (もちろん、コンパイラ固有)。
  • クラスのアラインメントの変更: データ メンバーの変更、アラインメントを人為的に膨らませるトリック (共用体) がありますが、デフレートするには、コンパイラ固有のプラグマまたは属性と準拠したハードウェアが必要です。
  • vtable のレイアウトの変更: 仮想メソッドを追加すると、vtable 内の以前の仮想メソッドのオフセットが変更される場合があります。gcc の場合、vtable は宣言順に配置されるため、仮想メソッドを最後に追加すると機能します... ただし、vtable レイアウトが派生クラスと共有される可能性があるため、基底クラスでは機能しません。冷凍と考えるのが一番
  • 関数のシグネチャの変更: シンボルの名前は、通常、関数自体の名前とその引数の型の両方に依存します (メソッドの場合は、クラスの名前とメソッドの修飾子)。引数にトップレベルを追加できますがconst、とにかく無視され、通常は戻り値の型を変更できます (ただし、これには他の問題が伴う可能性があります)。デフォルト値でパラメータを追加するとABI壊れることに注意してください。シグネチャに関する限り、デフォルトは無視されます。冷凍と考えるのが一番
  • 以前にシンボルをエクスポートした関数またはクラス (つまり、直接または継承された仮想メソッドを持つクラス) を削除します。

1 つまたは 2 つのポイントを忘れている可能性がありますが、これでしばらくは作業を進めることができます。

ABI の例: Itanium ABI

于 2011-11-18T15:04:35.847 に答える
5

正式には...クラスの2つの異なるバージョンに対してコンパイルされたファイルをリンクすると、未定義の動作である1つの定義ルールに違反しました。実際には...バイナリ互換性を損なう唯一のことは、データメンバーまたは仮想関数(非仮想関数は問題ありません)の追加、関数の名前またはシグネチャの変更、または基本クラスに関連するものです。これは普遍的なことのようです。規則が異なるコンパイラを私は知りません。

于 2011-11-18T15:12:58.810 に答える