Last Update 2021/10/28
-Wsizeof-pointer-memaccess
特定の文字列およびメモリ操作の関数の引数がsizeof式を使用して、バイト長の指定などで誤りが疑われる場合に警告を出力
テスト概要
オプション無し、-Wsizeof-pointer-memaccess、-Wallの各オプションを使用した際の警告出力例
実行環境
GCC-8.2.0
GNU C Library 2.28
GNU Binutils 2.31.1
GNU C Library 2.28
GNU Binutils 2.31.1
コード例・出力内容中の表記
・実行例中の太字表記部分は、コマンドなどの入力された文字列を示します。
・「︙」や「...」の着色省略表記は、 実際のソースコードや出力内容などを省略加工した部分を示します。
・「︙」や「...」の着色省略表記は、 実際のソースコードや出力内容などを省略加工した部分を示します。
使用ファイル
sample.c
#include <stdio.h>
#include <string.h>
int main(void)
{
char s1[20] = "12345";
char s2[20];
char *p = s2;
memset(s2, '\0', sizeof(s2));
/* sizeofの対象がポインタ */
printf("sizeof(p) = %ld --- ", sizeof(p));
memset(p, 'a', sizeof(p));
printf("[%s] [%s]\n", s1, s2);
/* sizeofの対象が配列 */
printf("sizeof(s2) - 1 = %ld --- ", sizeof(s2) - 1);
memset(p, 'b', sizeof(s2) - 1);
printf("[%s] [%s]\n", s1, s2);
/* sizeofの対象が配列先頭のアドレス */
printf("sizeof(&s2[0]) = %ld --- ", sizeof(&s2[0]));
memcpy(&s2[0], s1, sizeof(&s2[0]));
printf("[%s] [%s]\n", s1, s2);
/* sizeofの対象が配列 */
printf("sizeof(s2) - 1 = %ld --- ", sizeof(s2) - 1);
memcpy(&s2[0], s1, sizeof(s2) - 1);
printf("[%s] [%s]\n", s1, s2);
return 0;
}
動作テスト
オプション無しでコンパイルを実行
$ gcc sample.c 警告無し
$ ./a.out
sizeof(p) = 8 --- [12345] [aaaaaaaa]
sizeof(s2) - 1 = 19 --- [12345] [bbbbbbbbbbbbbbbbbbb]
sizeof(&s2[0]) = 8 --- [12345] [12345]
sizeof(s2) - 1 = 19 --- [12345] [12345]
$
-Wsizeof-pointer-memaccessオプションを指定してコンパイルを実行
$ gcc -Wsizeof-pointer-memaccess sample.c
sample.c: In function ‘main’:
sample.c:14:23: warning: argument to ‘sizeof’ in ‘memset’ call is the same expression as the destination; did you mean to provide an explicit length? [-Wsizeof-pointer-memaccess]
memset(p, 'a', sizeof(p));
^
sample.c:24:27: warning: argument to ‘sizeof’ in ‘memcpy’ call is the same expression as the destination; did you mean to remove the addressof? [-Wsizeof-pointer-memaccess]
memcpy(&s2[0], s1, sizeof(&s2[0]));
^
$ 各々の関数についての修正の可能性についてのコメントを出力
-Wallオプションを指定してコンパイルを実行
$ gcc -Wall sample.c
sample.c: In function ‘main’:
sample.c:14:23: warning: argument to ‘sizeof’ in ‘memset’ call is the same expression as the destination; did you mean to provide an explicit length? [-Wsizeof-pointer-memaccess]
memset(p, 'a', sizeof(p));
^
sample.c:24:27: warning: argument to ‘sizeof’ in ‘memcpy’ call is the same expression as the destination; did you mean to remove the addressof? [-Wsizeof-pointer-memaccess]
memcpy(&s2[0], s1, sizeof(&s2[0]));
^
$ -Wsizeof-pointer-memaccessオプションは-Wallでも有効となる