从文本文件中读取单词并存储到 C 中的动态数组 Valgrind 错误中
Posted
技术标签:
【中文标题】从文本文件中读取单词并存储到 C 中的动态数组 Valgrind 错误中【英文标题】:Read in Words from Text File and Store into Dynamic Array Valgrind Errors in C 【发布时间】:2016-02-02 03:29:47 【问题描述】:我正在尝试使用 fscanf 从 C 中的文本文件中读取单词并将它们放入动态分配的数组中。但是,我在 Valgrind 中不断收到错误,并且(空)字符似乎在我的输出中弹出。我创建了一个双指针 **str_array 来保存每个字符数组,并最初为 4 个字符数组分配足够的空间。 fscanf 运行并将读取的字符串存储到 str[] 中,我使用 strcpy 将 str[] 的字符串复制到 str_array 中。如果 str_array 需要保存更多字符串,我会重新分配内存。
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
char str[80];
int word_alloc = 0;
int word_count = 0;
char **str_array;
FILE *file;
file = fopen(argv[1], "r");
// Allocate memory to the array of strings (char arrays)
word_alloc = 4;
str_array = (char **) malloc(sizeof(char*) * word_alloc);
while (fscanf(file, "%s", str) != EOF)
// If there are more than 4 strings, double size
if (word_count > word_alloc)
word_alloc *= 2;
str_array = (char **) realloc(str_array, sizeof(char*) * word_alloc);
str_array[word_count] = (char *) malloc(sizeof(char) * (strlen(str) + 1));
strcpy(str_array[word_count], str);
++word_count;
int i = 0;
for (; i<word_count; i++)
printf("Word: %s\n", str_array[i]);
i = 0;
for (; i<word_count; i++)
free(str_array[word_count]);
free(str_array);
fclose(file);
return 0;
这是 Valgrind 错误代码。
==6254== Memcheck, a memory error detector
==6254== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==6254== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==6254== Command: ./a.out readin-test.txt
==6254==
==6254== Invalid write of size 8
==6254== at 0x4008A6: main (readin-test.c:25)
==6254== Address 0x51fc2e0 is 0 bytes after a block of size 32 alloc'd
==6254== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==6254== by 0x400835: main (readin-test.c:16)
==6254==
==6254== Invalid read of size 8
==6254== at 0x4008C0: main (readin-test.c:26)
==6254== Address 0x51fc2e0 is 0 bytes after a block of size 32 alloc'd
==6254== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==6254== by 0x400835: main (readin-test.c:16)
==6254==
==6254== Conditional jump or move depends on uninitialised value(s)
==6254== at 0x4C2BDA2: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==6254== by 0x40094A: main (readin-test.c:37)
==6254== Uninitialised value was created by a heap allocation
==6254== at 0x4C2CE8E: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==6254== by 0x400871: main (readin-test.c:22)
==6254==
==6254==
==6254== HEAP SUMMARY:
==6254== in use at exit: 999 bytes in 173 blocks
==6254== total heap usage: 181 allocs, 8 frees, 5,631 bytes allocated
==6254==
==6254== 999 bytes in 173 blocks are definitely lost in loss record 1 of 1
==6254== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==6254== by 0x4008A5: main (readin-test.c:25)
==6254==
==6254== LEAK SUMMARY:
==6254== definitely lost: 999 bytes in 173 blocks
==6254== indirectly lost: 0 bytes in 0 blocks
==6254== possibly lost: 0 bytes in 0 blocks
==6254== still reachable: 0 bytes in 0 blocks
==6254== suppressed: 0 bytes in 0 blocks
==6254==
==6254== For counts of detected and suppressed errors, rerun with: -v
==6254== ERROR SUMMARY: 186 errors from 4 contexts (suppressed: 0 from 0)
【问题讨论】:
"%s"
在 scanf 中应该是 "%79s"
。当word_count == word_alloc
时,你也写越界了。
使用calloc
分配(或将新内存初始化为NULL)以消除Conditional jump or move depends on uninitialised value(s)
...并且.. 不要 强制转换malloc
的返回值。 ..
大小为 8 的无效写入是因为您需要在 word_count >= word_alloc 时重新分配(不仅仅是 > ),因为 C 数组是从零开始的。您存储字 0、1、2、3(即 4 个字指针,所有您分配的!)所以当 word_count=4 时,您必须在写入目标位置 [4] 之前重新分配。
【参考方案1】:
free
循环中有错误:
i = 0;
for (; i<word_count; i++)
free(str_array[word_count]);
数组索引应该是i
,而不是word_count
。
【讨论】:
以上是关于从文本文件中读取单词并存储到 C 中的动态数组 Valgrind 错误中的主要内容,如果未能解决你的问题,请参考以下文章