5

llvm/compiler-rt/clang の 3.1 リリースをビルドしました。-fcatch-undefined-behavior が本当に何かを行うかどうかを確認しようとしています。これまでのところ、運がありません。たとえば、コンパイルして実行します

#include <stdio.h>
#include <stdlib.h>

int main() {
    int* x = malloc(sizeof(int) * 10);
    printf("%d\n", x[20]);
    return 0;
}

$ /usr/local/bin/clang -fcatch-undefined-behavior undef_test.c && ./a.out
0

本当に単純なものが欠けていますか?

4

2 に答える 2

4

はい:x配列ではありません。

ドキュメントから:

-fcatch-undefined-behavior : ランタイム コード生成を有効にして、未定義の動作をチェックします。このオプションはデフォルトでオフになっており、Clang が未定義のランタイム動作のランタイム チェックを追加するかどうかを制御します。チェックが失敗した場合、失敗__builtin_trap()を示すために使用されます。チェックは次のとおりです。

  • 1 つのオペランドの静的な型が配列型から減衰した変数であり、もう 1 つのオペランドが配列のサイズより大きいかゼロより小さい添字。
  • シフト量が左辺の昇格されたビット幅以上、またはゼロ未満のシフト演算子。
  • 制御フローが __builtin_unreachable に達した場合。
  • llvm がより多くの __builtin_object_size サポートを実装すると、__builtin_object_size が有効なメモリにアクセスしていないことを示すオブジェクトの読み取りと書き込みが行われます。ビットフィールドとベクトルはまだチェックされていません。

添字チェックをテストしたかったのだと思いますが、残念ながら配列を構築していませんでした。( からmalloc) メモリ領域を構築し、それを配列として解釈することを選択しました。しかし、コンパイラの観点からは、それは単なるメモリの塊です ( mallocisの戻り値の型より覚えておいてvoid*ください)。

おそらく、次の方法でこの動作をテストできます。

int main() {
    int x[10] = {};
    printf("%d\n", x[20]);
}

それ以外の場合、特定のメモリ問題トラッカーについては、Address Sanitizer プラグインを調べる必要があります。

于 2012-06-28T09:36:08.040 に答える
1

-fcatch-undefined-behaviorランダムなポインター逆参照を処理しません。このケースを処理するには、コンパイラは、ポイントされたデータのサイズをポインターと共に格納し、そのサイズをすべての関数呼び出しで渡す必要があります。これは既存の ABI と互換性がなく、プログラムがリンクするすべてのライブラリを再コンパイルする必要があります。

これmallocはよく知られた関数であり、コンパイラは返されたポインターが要求されたサイズの配列を指していると想定することができます。

mallocしかし、それが戻ってくる可能性があることを忘れているでしょうNULL。コンパイラーがポインターが でないと想定した場合、NULLすべてのチェックを最適化しますNULL(非常に危険です)。コンパイラが、ポインタが であるNULL、または要求されたサイズの配列へのポインタであると想定した場合、管理が少し複雑になります (これについてはまだ説明freereallocていません)。さらに、チェックmallocせずに -ated ポインターを逆参照するコードはNULL、未定義の動作と見なされます。

言うまでもなく、あなたのプログラムは標準ライブラリにリンクするのではなくmalloc、別の意味を持つ のカスタム実装を提供するライブラリにリンクするかもしれません。

于 2012-06-28T09:45:24.600 に答える