需要我的代码帮助。我用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)
我在网上搜索了答案,这个错误似乎与分配的内存不是以空值终止的事实有关。但是我在函数结束时做了空终止内存。
答案 0 :(得分:2)
此代码接近结尾:
size_t word_len = strlen(file_words[i].word);
file_words[i].word[word_len+1] = '\0';
毫无意义。 strlen()
的整个点是查找字符串终止,因此使用它来计算终止位置是不合逻辑的。
它还包括一个一个错误,但这当然是多余的。
您必须在构建时终止字符串,因为只有这样才知道它的长度。还记得为终止字符分配空间。