2017-06-16 18 views
-3

私のコードの助けが必要です。 valgrindでプログラムを実行してエラーが発生しました。 "アドレス0x520448aは、サイズ10のalloc'dブロックの後に0バイトです。"このコードは、ファイルから単語を取得し、プロパティchar *wordを持っているとline_numberをint型構造体への各単語を保存します。C - 解決方法 "アドレスはブロックサイズalloc'dの後0バイトです"

==19981== Invalid read of size 1 
==19981== at 0x4C30F74: strlen (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==19981== by 0x401330: process_file_words (in /home/avishay/Desktop/haptoha-C/maman23/myprog) 
==19981== by 0x400C3C: main (in /home/avishay/Desktop/haptoha-C/maman23/myprog) 
==19981== Address 0x520448a is 0 bytes after a block of size 10 alloc'd 
==19981== at 0x4C2FB55: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==19981== by 0x40112D: process_file_words (in /home/avishay/Desktop/haptoha-C/maman23/myprog) 
==19981== by 0x400C3C: main (in /home/avishay/Desktop/haptoha-C/maman23/myprog) 
==19981== 
==19981== Invalid write of size 1 
==19981== at 0x401357: process_file_words (in /home/avishay/Desktop/haptoha-C/maman23/myprog) 
==19981== by 0x400C3C: main (in /home/avishay/Desktop/haptoha-C/maman23/myprog) 
==19981== Address 0x520448b is 1 bytes after a block of size 10 alloc'd 
==19981== at 0x4C2FB55: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==19981== by 0x40112D: process_file_words (in /home/avishay/Desktop/haptoha-C/maman23/myprog) 
==19981== by 0x400C3C: main (in /home/avishay/Desktop/haptoha-C/maman23/myprog) 

\

void process_file_words(FILE *exist_file, struct file_word *file_words){ 
    enum status {IN, OUT}; 
    int i, c, next_char; 
    int prev_char = '\0'; 
    int line_number = 1; 
    int j = 0; 
    size_t size = 10; 
    int state = OUT; 
    bool in_decimal_number = false; 

    /* get all words in the file using fgetc */ 
    for(;;) { 
     c = fgetc(exist_file); 
     if (feof(exist_file)){ 
      break; 
     } 
     next_char = fgetc(exist_file); 
     /* Move the file position back to it's original position */ 
     if (next_char != EOF) { 
      fseek(exist_file, -1, SEEK_CUR); 
     } 
     /* Check if we are in a middle of a decimal number */ 
     if (c == '.') { 
      if (isdigit(next_char) && prev_char && isdigit(prev_char)) { 
       in_decimal_number = true; 
      } 
     } else if (c == '\n') { 
      line_number++; 
     } 
     /* If we are outside of a word, create new word */ 
     if ((isalpha(c) || isdigit(c)) && state == OUT) { 
      /* increase the words count as we have a new word */ 
      words_count_index++; 
      /* allocate memory for the new word */ 
      file_words[words_count_index].word = calloc(size, sizeof(char)); 
      assert(file_words[words_count_index].word); 
      file_words[words_count_index].word[j++] = (char) c; 
      file_words[words_count_index].line_number = line_number; 
      state = IN; 
     } else if ((isalpha(c) || isdigit(c) || in_decimal_number) && state == IN) { 
      /* check if more memory is needed */ 
      if (j == size) { 
       if ((file_words[words_count_index].word = realloc(file_words[words_count_index].word, (size *= 2) * sizeof(char))) == NULL) { 
        fprintf(stderr, "Error trying to reallocate memory.\n"); 
        exit(1); 
       } 
      } 
      file_words[words_count_index].word[j++] = (char) c; 
     } else { 
      /* we are outside of a word, reset variables */ 
      state = OUT; 
      j = 0; 
      size = 10; 
     } 

     if (in_decimal_number) { 
      in_decimal_number = false; 
     } 
     prev_char = c; 
    } 

    /* save exact words count to a variable */ 
    words_count = words_count_index + 1; 

    /* null-terminate the words array */ 
    for (i = 0; i < words_count; i++) { 
     size_t word_len = strlen(file_words[i].word); 
     file_words[i].word[word_len+1] = '\0'; 
    } 
} 

私はウェブで答えを検索し、このエラーがいるようです割り当てられたメモリがヌル終了していないという事実に関連している。しかし、私は関数の最後にヌル終了しました。

+3

これは、strlenが割り当てられたストレージの最後を過ぎて読み取っていることを意味します。なぜそれができますか? –

+0

'FOREVER'は' for(); 'や' while(1) 'のマクロです。 – InternetAussie

+0

なぜダウン票? – Avishay28

答えて

2

終わり近くにこのコード:

size_t word_len = strlen(file_words[i].word); 
file_words[i].word[word_len+1] = '\0'; 

は意味がありません。 strlen()は、文字列の終端を検索するため、終端を置く場所を計算するために使用するのは理にかなっていません。

これにはoff-by-oneエラーも含まれていますが、それはもちろん冗長です。

文字列を作成するときに文字列を終了する必要があります。その文字列の長さは分かります。また、終了文字のスペースを割り当てることを忘れないでください。

+0

文字列の作成中に 'stlern()'を削除してヌル終了しましたが、2番目のエラーは引き続き表示されます。どんな考え? – Avishay28

関連する問題