1

このコード スニペットでは、Init() 関数は、構造体のすべてのメンバー変数を埋めるオンデマンドの初期化子として機能します。これは、スタック上の大きな配列のすべてのメンバーがデフォルト コンストラクターを呼び出さないようにするために行われます。

struct Foo {
    int m_Member;
    void Init(int i);
};

void Foo::Init(int i) {
    m_Member = i;
    // Many other members initialized here.
}

void SomeFunction(int n) {
    Foo buffer[64];
    assert(n <= 64);
    // Explicitly initialize what is needed.
    for (int i = 0; i < n; ++i) {
        buffer[i].Init(i * 3);
    }
    // Use buffer[0] - buffer[n-1] somehow.
}

これにより、VS2012 で /analyze を使用して静的分析エラーが発生します。

warning C6001: Using uninitialized memory 'buffer'.: Lines: 17, 19, 20

この警告が発生しないように Foo::Init() に注釈を付ける方法を探しています。警告を消す方法は他にもたくさんあります。

  • 空のコンストラクターの追加
  • Init() をコンストラクターに移動し、placement new をループ内で呼び出す

しかし、コードの構造を変更することは避けたいと思います。

次の注釈を試してみましたが、成功しませんでした:

void _At_(this, _Out_) Init();

この構文は受け入れられますが、警告を次のように変更するだけです。

warning C6001: Using uninitialized memory 'buffer'.: Lines: 18, 20, 21
warning C6001: Using uninitialized memory 'buffer[BYTE:0]'.: Lines: 18, 20, 21

この Init() 関数の意図を静的分析エンジンに宣言する方法を知っている人はいますか?

4

4 に答える 4

0

余分なヘルパーを追加するにはあまりにも醜いですか?

struct Foo {
    int m_Member;
    void Init(int i);
};

void Foo::Init(int i) {
    m_Member = i;
    // Many other members initialized here.
}

void Initialize(__in_bcount(sizeof(Foo) * n) Foo* buffer, int n) {
    // Explicitly initialize what is needed.
    for (int i = 0; i < n; ++i) {
        buffer[i].Init(i * 3);
    }
}

void SomeFunction(int n) {
    Foo buffer[64];
    assert(n <= 64);
    Initialize(buffer, n);
    // Use buffer[0] - buffer[n-1] somehow.
}
于 2013-01-28T18:57:41.200 に答える
0

あなたの質問はややとらえどころのないものです。SomeFunctionの取得を示しましたが、メソッドまたはコンストラクターintの注釈が必要です。Init

表示されている警告は完全に正しいものでありassert、警告を非表示にすることはありません。がより大きいifかどうかをチェックしてリセットする必要があります(または何か他のことをしますが、 when をループしないでください)。n64nn>=64

__in_bcount注釈については、または同様の代替手段を使用する必要があります。例:

bool SetBuffer(__in_bcount(8) const char* sBuffer);

これは、sBufferが8 バイト(要素ではない)であることを示しています。

詳細については、この記事を参照してください。

于 2013-01-26T05:20:16.987 に答える
-2

デフォルトのコンストラクター (Init() を呼び出す) を追加するだけです。それの何が問題なのですか?

[編集] 根本的な問題は、静的アナライザーやコンパイラーに嘘をつく方法ではありません。foo を初期化されていない状態のままにしないようにする方法です。デフォルトのコンストラクターを追加しても問題はありません。やりたくないという欲求はリスクを伴うと思います。

おそらく、一部のクライアントは、その不十分に構築された foo クラスを使用し (作成してからずっと経ってから、なくなってからずっと経ってから)、おそらく .Init() を呼び出すのを忘れるでしょう?? じゃあ何?初期化されていないデータが残ります。

そのルールを適用しようとしている場合、静的分析は役に立ちません。

屋根を載せる前に土台のお手入れをしましょう。

于 2013-01-26T00:14:21.550 に答える