3

C ++で作業している大規模なアプリケーションがあり、インライン関数が間違った値を返すクラスがあります。1つのエントリでオフセットされているようです。

コードの設定方法の例を次に示します。

class Test
{

private:
    uint myVal1;    
    uint myVal2;
    uint myVal3;
    uint myVal4;

public:
    uint myFunct1() const { return myVal1 };
    uint myFunct2() const { return myVal2 };
};

私たちが見ているのは、myFunct1がmyVal2を返し、myFunct2がmyVal3を返すことです。関数をインライン化しないと、すべてが期待どおりに機能します。

なぜこれが起こるのかについてのアイデアはありますか?

前もって感謝します。

4

2 に答える 2

12

(上記で投稿したものは、実際にはいくつかのヘッダーファイルからのフラグメントであると思います。)

このようなことは通常、プログラム内のさまざまなソースファイルが、クラスのパッキングや配置設定など、さまざまなメモリレイアウト関連の設定でコンパイルされている場合に発生します。ヘッダーファイルはこれらの異なる変換ユニットに含まれており、メモリレイアウト設定の不一致のために解釈が異なります。

これらの変換ユニット間でオブジェクトを渡し始めるTestと、問題が明らかになります。1つの変換ユニットがTest1つのメモリレイアウトでオブジェクトを作成し、次に別の変換ユニットがそれを読み取ったり、まったく異なるメモリレイアウトを想定してオブジェクトに書き込んだりします。あなたの場合、各翻訳単位で異なって解釈されるのはインライン関数です。

メンバー関数を非インライン関数として定義すると、それらは、それらが定義されているソースファイルに固有のクラスメモリレイアウトを想定します。これにより、問題が一掃され、「機能」するようになります(アクセス機能が1つのメモリレイアウトに関連付けられているため)が、それでもなお良い状況ではありません。それでも、将来的には同様の性質のさまざまな問題が発生する可能性があります。

プログラム内のすべてのソースファイルが、まったく同じクラスのメモリレイアウト設定でコンパイルされていることを確認してください。

PSフレッドがコメントで述べたように、翻訳ユニット間のクラスメモリレイアウトの不一致は、ソースファイルが依存するヘッダーファイルを変更した後にソースファイルを再コンパイルするのを忘れるなどの無作法なものによって引き起こされる可能性があります。

このような問題のもう1つの「人気のある」原因は、プリプロセッサディレクティブに依存するクラス定義です(つまり、#ifdef/#endifセグメントによって「カスタマイズ」されたクラスレイアウト)。#defineヘッダーファイルを含むソースファイルで重要なことを忘れると、そのソースファイルのクラスのメモリレイアウトが異なる可能性があります。

于 2011-02-09T00:01:38.393 に答える
3

いいえ、インライン化された関数は、(もちろん) インライン化されていない関数と同じ結果を得る必要があります。したがって、問題は、表示されていないコード内の別の場所にあるはずです。おそらく、プライベートメンバーの値を魔法のように設定するものでしょうか?

于 2011-02-09T00:02:45.493 に答える