从文本文件中读取单词并存储到 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 错误中的主要内容,如果未能解决你的问题,请参考以下文章

在C++中如何读取文本中的数据存储为数组变量?

读取单词并将它们存储到数组中

在c中使用多维数组存储来自用户的一行,并根据字长按降序返回该行中的单词

动态读取文本文件并放入 C 中的指针字符数组

如何从文本文件创建二维数组并在 c 中打印到新文件

C ++:从文本文件中读取单行,按字母顺序对单词进行排序