C - 如何解决"地址是大小分配块后的0字节' d"

时间:2017-06-16 08:46:45

标签: c valgrind

需要我的代码帮助。我用valgrind运行程序并得到错误: "地址0x520448a是大小为10的块后的0字节' d"。此代码从文件中获取单词并将每个单词保存到具有属性char *word和int line_number的结构中:

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';
    }
}

\

==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)

我在网上搜索了答案,这个错误似乎与分配的内存不是以空值终止的事实有关。但是我在函数结束时做了空终止内存。

1 个答案:

答案 0 :(得分:2)

此代码接近结尾:

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

毫无意义。 strlen()的整个是查找字符串终止,因此使用它来计算终止位置是不合逻辑的。

它还包括一个一个错误,但这当然是多余的。

您必须在构建时终止字符串,因为只有这样才知道它的长度。还记得为终止字符分配空间。