【C言語】
Segmentation fault(コアダンプ)を調べる方法

静的解析で敵を見つける

●gcc -Wall -Wextra -Oでコンパイルして警告を直す

clang -Wall -Wextra -Oでもコンパイルして
警告を直しましょう。


gcc -fanalyzer -O2でコンパイルして警告を直す

clang –analyze -O2でもコンパイルして
警告を直しましょう。


●clang-tidyやcppcheckも使ってみる

使い方はこちら。

https://bugs-c.info/uncategorized/3248/

ここまでやって問題解決できない場合
静的解析はあきらめましょう。


動的解析で敵を見つける

●gccの場合
gcc -fsanitize=address -g でコンパイルして実行してください。

●clangの場合
clang -fsanitize=address -g でコンパイルして実行してください。

以下のようにエラー個所(ファイル名行番号)を教えてくれます。

-gオプションを付けないと行番号までは教えてくれません。
-Oオプション(最適化)の有無でエラーが出たり出なかったりする時があります。

前略
SUMMARY: AddressSanitizer: heap-buffer-overflow /mnt/中略/x.c:10 in main
後略

敵 segmentation faultはこんな時出ます

出ない時もあります。
再現性が無いので苦労します。

●未初期化ポインタを間接参照しない事

#include <stdio.h>
#include <stdlib.h>
int main(void){
    int x ;
    int *p ;    //未初期化ポインタ
    x   = 1234 ;
    *p  = 5678 ;

    char  *str; //未初期化ポインタ
    printf("数字を入れてね");
    scanf("%s",str);
    printf("%d\n",atoi(str));
}

●NULLポインタを間接参照しない事

#include <stdio.h>
int main(void){
    char    x  = '\0';
    char    *p = NULL;
    x   = 'A' ;
    *p  = 'B' ;//NULLポインタ間接参照
    printf("%c:%c\n",x,*p);
}

●配列の添字が大きすぎる(基本を勉強)

#include <stdio.h>
int main(void){
    int     buf[10] = {1,2,3,4,5,6,7,8,9,10};
    //buf[10]で宣言したらbuf[9]までしか使えない
    printf("%d\n",buf[10]);
}

●配列の添字が大きすぎる(for文回り過ぎ)

#include <stdio.h>
int main(void){
    int     buf[10];
    
    //  int i = 0; i < 10;i++){ が正解   
    for(int i = 1; i <= 10;i++){
        buf[i] = i;
    }
    printf("%d\n",buf[0]);
}

●自動変数配列のサイズが大きすぎる

#include <stdio.h>
int main(void){
    //自動変数配列のサイズが多き過ぎる
    char    buf[0x7FFFffff] = {0};
    printf("%d\n",buf[0]);
}

●fclose(NULL)を実行しちゃ駄目

#include <stdio.h>
int main(void){
    FILE *fp = fopen("存在しなファイル","re");
    if(fp == NULL){
        perror(NULL);
        fclose(fp);
    }
}

●fgets()のバッファが小さすぎ(ケチらない事)

#include <stdio.h>
#include <stdlib.h>
int main(void){
    //終端文字の考慮がない。
    //ピッタリサイズでなくて余裕を持たせる。
    char    buf[4]; 
    printf("4桁の数字を入れて下さい");
    fgets(buf,BUFSIZ,stdin);
    printf("%d\n",atoi(buf));
}

●malloc()で確保したサイズが小さい(型違い)

#include <stdio.h>
#include <stdlib.h>
int main(void){
    //sizeof(int)はsizeof(double)の間違い
    double *p = malloc(sizeof(int));
    if(p == NULL){
        perror(NULL);
        return 1;
    }
    *p = 3.14 ;
    printf("%lf\n",*p);
    free(p);
}

●文字列リテラルへに書いちゃ駄目

#include <stdio.h>
int main(void){
    char    *p = "string" ;
    *p = 'X' ;
}