如何从输入中存储未知数量的未知长度的字符串数组?

时间:2016-12-16 17:49:09

标签: c valgrind c89

我无法从输入中将字符串存储在数组中。我希望从以EOF结尾的输​​入存储它,并能够存储任意长度的任意数量的字符串。这是我的代码:

char **list = (char**)malloc(sizeof(char*));
char c = getchar();
int i, j, count = 0;
int size = 0;
char * string = NULL
while (c != EOF)
{
    size = 0;
    while (c != EOF && c != '\n')
    {
        string = (char*)realloc(string,size+1); //line 210
        string[size] = c;
        size++;
        c = getchar();
    }
    list = (char**)realloc(list, (count+1)*sizeof(char*));
    list[count] = string;
    ++count;
    string = NULL;
    c = getchar();
}
for (j = 0; j < count; ++j) //trying to print out all the strings
{
    printf("%s\n", list[j]); //line 237
}
free(string);
free(list);
return (EXIT_SUCCESS);

我知道我也应该测试所有的分配是否成功,但这不是我现在的问题。使用gcc -Wall -pedantic编译时程序可以正常工作,但valgrind会出现以下错误:

==2601== Memcheck, a memory error detector
==2601== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==2601== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==2601== Command: ./a.out -g
==2601== 
asd
dsa
==2601== Invalid read of size 1
==2601==    at 0x4C30F74: strlen (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==2601==    by 0x4EA95DB: puts (ioputs.c:35)
==2601==    by 0x4008E8: main (testing.c:237)
==2601==  Address 0x52035c3 is 0 bytes after a block of size 3 alloc'd
==2601==    at 0x4C2FD5F: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==2601==    by 0x40080D: main (testing.c:210)
==2601== 
asd
dsa
==2601== 
==2601== HEAP SUMMARY:
==2601==     in use at exit: 12 bytes in 4 blocks
==2601==   total heap usage: 14 allocs, 10 frees, 2,101 bytes allocated
==2601== 
==2601== LEAK SUMMARY:
==2601==    definitely lost: 12 bytes in 4 blocks
==2601==    indirectly lost: 0 bytes in 0 blocks
==2601==      possibly lost: 0 bytes in 0 blocks
==2601==    still reachable: 0 bytes in 0 blocks
==2601==         suppressed: 0 bytes in 0 blocks
==2601== Rerun with --leak-check=full to see details of leaked memory
==2601== 
==2601== For counts of detected and suppressed errors, rerun with: -v
==2601== ERROR SUMMARY: 2 errors from 1 contexts (suppressed: 0 from 0)

1 个答案:

答案 0 :(得分:1)

代替程序末尾的free string,您需要释放为您读取的每个字符串分配的内存:

for (j = 0; j < count; j++)    
        free(list[j]);
free(list);

要解决"Invalid read of size 1"错误,您需要更改:

string = realloc(string,size+2);

您使用size作为string的索引,因此您需要在为&#39; \ 0&#39;添加空格之前增加此值。在分配中。更好的变量名称可以帮助避免这个问题。请考虑将size更改为index

另请注意,为了存储c字符,您需要intEOF,因此请更改:

int c = getchar();

此外,此代码无法使用NUL终止字符串。你需要添加:

...
string[size] = '\0';    // NUL terminate string

list = realloc(list, (count+1)*sizeof(*list));
...

当您在程序开头初始化list时,无需分配空间,而您最终还是realloc,所以:

char **list = NULL;

请注意,我已通过调用malloc()realloc()删除了演员。这些在C中不是必需的,并且主要用于使代码混乱。同样,我使用sizeof(char*)代替sizeof(*list),而不是容易出错且更清晰。