
gccユーザーへの朗報-gcc 5.1以降を使用している場合、関数パラメーターとして宣言された配列のサイズを計算する際に、次の一般的なエラーをすばやく見つけやすくなります。
void something( char arr[100] ) {
パラメーターは既知のサイズの配列として宣言されますが、CおよびC ++コンパイラーの観点からは、
char *型のポインターであるため、
sizeof(arr)は
sizeof(char *)と同じ値を与えます-4または8の可能性が高い合計は期待どおりに機能しません。
別のオプション:
void something( char encryptionKey[9000] ) {
ここでは、開発者は
一部のデータをゼロで
上書きしたかったのですが、エラーのため、最初の数バイトのみが上書きされます。 このようなエラーは、最初のエラーよりもテストで見つけるのが困難です。
gcc 5.1以降では、このようなコードを見つけやすくするために、そのようなコードに対して警告が発行され、デフォルトで有効になっています。
一部の読者は、上記の例からコードの作者の手の曲率についてコメントすることに急いでいます。 ただし、この問題は非常に一般的であるため、C ++コードでは、テンプレート関数で次のフォーカス(
ここから )を使用することをお勧めします。
template<typename StoredType, size_t Size> char ( &ArrayElementsCountHelper(StoredType( &Array )[Size]) )[Size]; #define countOfElements(Array) sizeof(ArrayElementsCountHelper (Array))
上記のコードで
countOfElements()を使用すると、コンパイルエラーが発生しますが、このコードは次のとおりです。
char arr[100] for( size_t index = 0; index < countOfElements(arr); index++ ) {
コンパイルし、正しく動作します。
sizeof(smth)/ sizeof(smth [0])を明示的に指定することに加えて、マクロも使用します。
上記のケースで新しい警告がどのように機能するかを見てみましょう。
gcc.godbolt.orgを
試して
みますまず、コンパイラーとしてgcc 4.9.2を選択します。デフォルトのパラメーターを使用すると、どの例でもサイズの計算が正しくないという警告は表示されません。 次に、gcc 5.1.0に変更します-ループのある例では、ループタイトルのある行を取得します
警告:配列関数パラメーター 'arr'の 'sizeof'は 'char *'のサイズを返します[-Wsizeof-array-argument]このコードでは:
void somethingExplicitCount( char arr[] ) { for( size_t index = 0; index < sizeof(arr)/sizeof(arr[0]); index++ ) {
同じ警告が発行されます。 同様にマクロコードで:
void somethingMacroCount( char arr[9000] ) { for( size_t index = 0; index < errorProneCountOfElements(arr); index++ ) {
書き直されたコードは警告も出します(デモンストレーションにのみポータブル
memset()を使用します):
void somethingMemset( char key[9000] ) {
利益。
特に注意すべきなのは、clangバージョン3.0が同じ警告を発行する方法をすでに知っているという事実です。 これ
はかつて LLVMブログで、これはclang固有の警告であり、gccはそうではない
と言われていました。 モーアはありません。
警告はデフォルトで有効になっています。開発者は問題コードを正しく修正するだけで済みます。
ドミトリー・メッシェリャコフ、
開発者製品部門