4

次のプログラムを検討してください。

struct abc
{
    int x[5];
    int y[5];
};

int main()
{
    struct abc test;
    test.y[0] = 10;
    printf("%d", test.x[5]);
}

( Is it legal to overrun one element of a struct to view another?から借用)

BoundsCheckerはこれをオーバーフローとして検出しません。この種のプログラミング エラーを検出するプログラムはありますか?

4

2 に答える 2

6

clang特別なフラグがオンになっていない場合でも、次のようになります。

$ clang example.c -o example
example.c:13:18: warning: array index of '5' indexes past the end of an array
      (that contains 5 elements) [-Warray-bounds]
    printf("%d", test.x[5]);
                 ^      ~
example.c:5:5: note: array 'x' declared here
    int x[5];
    ^
1 warning generated.

C++ としてコンパイルすると、同じ警告が出力されます。

于 2011-12-13T23:45:49.623 に答える
2

ここで目にするのは、BoundsChecker に関する厄介な、ほとんど知られていない秘密です。構造体のメンバーをまったく可視化できません。構造体の一部として配列を宣言すると、その構造体が自動的に割り当てられるか動的に割り当てられるかに関係なく、BoundsChecker は構造体を BLOB として認識します。その構造の境界を超えると、問題が報告されます。そうでなければ、いいえ。

とはいえ、数年前に、現在製品に同梱されているコードをいくつか作成しました。このコードは、非表示の構成オプションで呼び出すことができます。プロジェクト構成ファイル ( )のセクションに手動で行を挿入するEnableStructureMemberEnumeration=1と、構造体が自動的に(スタック)。[BC MemoryTracker].dpbcd

ただし、このオプションはプライムタイムに完全に対応できるわけではありません。STL に見られるような非常に複雑なクラスと構造に問題があります。さらに、上記の特定のテストケースには、別の問題があります。一般に、構造体/クラスを開始する配列とクラス オブジェクト自体を区別することはできません。どちらもメモリ内で同じアドレスを持っています。ただし、次のコードを検討してください。

struct _Type {
  int Array[5];
} Objects[10];

struct _Type *pObject = &Objects[5];
int *pInt = &Objects[0].Array[5];

どちらの場合も、最初はオフセットが 100 で、2 回目はオフセットが 20 の同じアドレスが表示ArrayされObjectsます。何をするのが悪いプログラムですか?

ああ、もう 1 つ: BoundsChecker は通常、配列の末尾を超えた最初の要素へのアクセスを無視します。これは、反復子が末尾の 1 要素だけを通過するコードが非常に多く存在するためです。これは誤ったエラーの大きな原因だったので、誰かがそれを変更して、オーバーランが次の場所 (およびそれ以降) に移動した場合にのみ文句を言うようにしました。ここでの問題は、反復子をインクリメントしましたが、本当にそれを使用するつもりですか?

したがって、当面の質問に対する答えは、BoundsChecker が実際にこの種のチェックをサポートしているということですが、文書化されていない「機能」を使用せずに、問題がないわけではありません。

于 2011-12-14T15:51:57.343 に答える