ページ 11

Segmentation fault (core dumped)の解決方法

Posted: 2021年8月20日(金) 16:46
by hanoha1631
以下は入力された文字列におい重複する文字はないか判定するコードです。コンパイルは通るのですが実行時入力後にSegmentation fault (core dumped)と表示され正しく実行されません。これはどこを誤ってしまっているのですか?
回答よろしくお願いします。

コード:

#include<stdio.h>
int main(){
  char *str;
  int i,j,count=0;
  scanf("%s",str);
  for(i=0;*(str+i)!='\0';i++){
    for(j=0;*(str+j)!='\0';j++)if(*(str+i)==*(str+j))count++;
    if(count>=2){ //自分以外の文字と遭遇したら2以上になるのでこれを判定法としました
      printf("重複あり\n");
      goto a;
    }
  }
  printf("重複なし\n");
 a:  return 0;
}

Re: Segmentation fault (core dumped)の解決方法

Posted: 2021年8月20日(金) 19:18
by みけCAT
ポインタ str を初期化せずにデリファレンスしてしまっているのが誤りです。
有効なバッファのアドレスに初期化してから入力の読み込みや処理をしないといけません。
また、バッファオーバーランを防ぐため、%s で文字列を読み込む時は読み込む最大の長さを指定するべきです。
この最大の長さは、最後にナル文字が入るため多くてもバッファサイズ-1にするべきです。
さらに、scanf() の戻り値は無視せず、意図した数の入力をちゃんと読み込めたか確認するべきです。

コード:

#include<stdio.h>
#include <stdlib.h>
int main(){
  char *str;
  int i,j,count=0;
  str=malloc(1024000); /* バッファを初期化する */
  if(str==NULL){
    printf("メモリ確保エラー\n");
    return 1;
  }
  if(scanf("%1023999s",str)!=1){ /* 読み込む最大の長さを指定し、読み込めたかを確認する */
    printf("入力エラー\n");
    return 1;
  }
  for(i=0;*(str+i)!='\0';i++){
    for(j=0;*(str+j)!='\0';j++)if(*(str+i)==*(str+j))count++;
    if(count>=2){ //自分以外の文字と遭遇したら2以上になるのでこれを判定法としました
      printf("重複あり\n");
      goto a;
    }
  }
  printf("重複なし\n");
 a:  free(str); return 0; /* 確保したバッファを開放する */
}

Re: Segmentation fault (core dumped)の解決方法

Posted: 2021年8月21日(土) 01:54
by box

コード:

  char *str;
まあ通常は適切なサイズの配列にするんでしょうね。
バッファーオーバーフローへの対応をすべきかどうかはお任せします。

Re: Segmentation fault (core dumped)の解決方法

Posted: 2021年8月21日(土) 09:45
by hanoha1631
回答ありがとうございます。不定な場所への入力は総じてSegmentation fault (core dumped)なんですね。エラー処理の件も心がけるようにします。
また重ねての質問失礼します。不定回避によってこのエラーはでなくなりましたが1文字の入力以外は全て重複ありと表示されてしまいます。
おそらくアルゴリズム自体に問題があると思うのですがそこを直せばいいのか分かりません。よろしければ教えていただけると嬉しいです。
$ ./a.out
w
重複なし

$ ./a.out
a
重複なし

$ ./a.out
aq
重複あり

$ ./a.out
aa
重複あり

Re: Segmentation fault (core dumped)の解決方法

Posted: 2021年8月21日(土) 12:31
by hanoha1631
#include<stdio.h>
#include<stdlib.h>

int main(){
char *str;
int i,j,count=0;
str=malloc(1024000);
scanf("%s",str);
for(i=0;*(str+i)!='\0';i++){
for(j=0;*(str+j)!='\0';j++)if(*(str+i)==*(str+j))count++;
if(count>=2){
printf("重複あり\n");
goto a;
}
count=0;
}
printf("重複なし\n");
a: return 0;
}

count=0;の処理を抜かしていたためにうまく実行されていませんでした。
御二方、回答ありがとうございました!!