セグメンテーション違反の発生について多くの質問を見ました SOのCプログラムでは、セグメンテーション違反を引き起こしているいくつかのケースに関する質問です。私の答えは以下に掲載されています。
以下の場合、プログラムを実行するとセグメンテーション違反が発生します。理由を特定できますか?
1)
char *str = "foo";
str[0] = 'b'; // << Segfault hre
2)
char str[] = "foo";
char *newStr = malloc(strlen(str));
strcpy(newStr, str);
free(newStr); // << Segfault here
3)
char *str = malloc(4 * sizeof(char));
str = "foo";
free(str); // << Segfault here
4)
char *str = malloc(4 * sizeof(char));
strcpy(str, "foo");
free(str);
if (str != NULL)
free(str); // << Segfault here
5)
char *str = "something and then foo";
printf("%s", str[19]); // << Segfault here
6)
typedef struct {
char *str;
}st;
...
st *s;
s = malloc(sizeof(st));
s->str = malloc(5);
free(s);
free(s->str); // << Segfault here
答え:
ケース 1:
char *str = "foo";
読み取り専用のテキストセグメントに文字列のアドレスを割り当て、2行目で行われたように書き込むことはできません:str[0] = 'b';
.
テキストを変更したい場合は char str[] = "foo";
を使用してください スタック上に文字の配列を作成します そのポインタを str に代入します。
ケース 2:
strlen
'\0'
を除いた文字列の長さを返します 最後の文字なので、strlen("foo") = 3
、 strcpy
の間 '\0'
を含む文字列をコピーします 文字なので、割り当てたよりも多くのバイトをコピーします。
ケース 3:
ケース 1 と同様に、str = "foo";
「foo」のアドレスを str
に割り当てます 、これは、割り当てられたメモリのアドレスと str
を失うことを意味します free
できないテキスト セグメントへのポインタが含まれるようになりました ヒープ上になく、読み取り専用メモリであるためです。
ケース 4:
free
関数は NULL
を割り当てません パラメーターとして受け取ったポインターへ (アドレスがないため、それを行うことはできません)。 free
を呼び出そうとしています すでに free
だったバッファ d.
ケース 5:
str[19]
char
です 、char ポインターではなく、"%s"
char *
を意味する文字列が必要です .多くのプラットフォームではアドレスとして扱われますが、この文字は不正なアドレスです。 printf()
受け取った引数をチェックしません。
ケース 6:
s->str
の使い方 s
の後 free
です dは間違っています。正しい使い方は、最初に free(s->str);
を呼び出すことです そして free(s);
を呼び出します . free
の前に内部割り当てメモリを解放する