セグメンテーション違反の取得



セグメンテーション違反の発生について多くの質問を見ました 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") = 3strcpy の間 '\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 の前に内部割り当てメモリを解放する