C - 字符串数组和神秘的 Valgrind 错误
C - Array of Strings & Mysterious Valgrind Error
我正在尝试分配一个二维字符串数组,其中最后一个成员始终是 NULL 指针,即空数组由单个 NULL 指针组成。我不断收到 Valgrind 错误,但我不知道为什么。
/*Initializes the string array to contain the initial
* NULL pointer, but nothing else.
* Returns: pointer to the array of strings that has one element
* (that contains NULL)
*/
char **init_array(void)
{
char **array = malloc(sizeof(char *));
array[0] = NULL;
return array;
}
/* Releases the memory used by the strings.
*/
void free_strings(char **array)
{
int i = 0;
while(array[i] != NULL){
free(array[i]);
i++;
}
//free(array[i]);
free(array);
}
/* Add <string> to the end of array <array>.
* Returns: pointer to the array after the string has been added.
*/
char **add_string(char **array, const char *string)
{
int i = 0;
while(array[i] != NULL){
i++;
}
array = realloc(array, (i+1) * sizeof(char *));
char *a = malloc(strlen(string)+1);
array[i] = malloc(strlen(string)+1);
strcpy(a, string);
strcpy(array[i], a);
free(a);
return array;
}
这是 Valgrind 错误:
==375== Invalid read of size 8 ==375== at 0x402FCE: add_string (strarray.c:40) ==375== by 0x401855: test_add_string (test_source.c:58) ==375== by 0x405F90: srunner_run_all (in /tmc/test/test) ==375== by 0x4028B2: tmc_run_tests (tmc-check.c:122) ==375== by 0x40256A: main (test_source.c:194) ==375== Address 0x518df08 is 0 bytes after a block of size 8 alloc'd ==375== at 0x4C245E2: realloc (vg_replace_malloc.c:525) ==375== by 0x402FF4: add_string (strarray.c:43) ==375== by 0x401855: test_add_string (test_source.c:58) ==375== by 0x405F90: srunner_run_all (in /tmc/test/test) ==375== by 0x4028B2: tmc_run_tests (tmc-check.c:122) ==375== by 0x40256A: main (test_source.c:194) ==375== ==375== Invalid read of size 8 ==375== at 0x4018F7: test_add_string (test_source.c:70) ==375== by 0x405F90: srunner_run_all (in /tmc/test/test) ==375== by 0x4028B2: tmc_run_tests (tmc-check.c:122) ==375== by 0x40256A: main (test_source.c:194) ==375== Address 0x518e308 is 0 bytes after a block of size 40 alloc'd ==375== at 0x4C245E2: realloc (vg_replace_malloc.c:525) ==375== by 0x402FF4: add_string (strarray.c:43) ==375== by 0x401855: test_add_string (test_source.c:58) ==375== by 0x405F90: srunner_run_all (in /tmc/test/test) ==375== by 0x4028B2: tmc_run_tests (tmc-check.c:122) ==375== by 0x40256A: main (test_source.c:194) ==375== ==375== Invalid read of size 8 ==375== at 0x402F8D: free_strings (strarray.c:25) ==375== by 0x401AA6: test_add_string (test_source.c:91) ==375== by 0x405F90: srunner_run_all (in /tmc/test/test) ==375== by 0x4028B2: tmc_run_tests (tmc-check.c:122) ==375== by 0x40256A: main (test_source.c:194) ==375== Address 0x518e308 is 0 bytes after a block of size 40 alloc'd ==375== at 0x4C245E2: realloc (vg_replace_malloc.c:525) ==375== by 0x402FF4: add_string (strarray.c:43) ==375== by 0x401855: test_add_string (test_source.c:58) ==375== by 0x405F90: srunner_run_all (in /tmc/test/test) ==375== by 0x4028B2: tmc_run_tests (tmc-check.c:122) ==375== by 0x40256A: main (test_source.c:194) ==375== ==376== Invalid read of size 8 ==376== at 0x402FCE: add_string (strarray.c:40) ==376== by 0x401DCD: test_make_lower (test_source.c:111) ==376== by 0x405F90: srunner_run_all (in /tmc/test/test) ==376== by 0x4028B2: tmc_run_tests (tmc-check.c:122) ==376== by 0x40256A: main (test_source.c:194) ==376== Address 0x518e6d8 is 0 bytes after a block of size 8 alloc'd ==376== at 0x4C245E2: realloc (vg_replace_malloc.c:525) ==376== by 0x402FF4: add_string (strarray.c:43) ==376== by 0x401DCD: test_make_lower (test_source.c:111) ==376== by 0x405F90: srunner_run_all (in /tmc/test/test) ==376== by 0x4028B2: tmc_run_tests (tmc-check.c:122) ==376== by 0x40256A: main (test_source.c:194) ==376== ==376== Invalid read of size 8 ==376== at 0x402F8D: free_strings (strarray.c:25) ==376== by 0x401F5C: test_make_lower (test_source.c:130) ==376== by 0x405F90: srunner_run_all (in /tmc/test/test) ==376== by 0x4028B2: tmc_run_tests (tmc-check.c:122) ==376== by 0x40256A: main (test_source.c:194) ==376== Address 0x518e9d0 is 0 bytes after a block of size 32 alloc'd ==376== at 0x4C245E2: realloc (vg_replace_malloc.c:525) ==376== by 0x402FF4: add_string (strarray.c:43) ==376== by 0x401DCD: test_make_lower (test_source.c:111) ==376== by 0x405F90: srunner_run_all (in /tmc/test/test) ==376== by 0x4028B2: tmc_run_tests (tmc-check.c:122) ==376== by 0x40256A: main (test_source.c:194) ==376== ==377== Invalid read of size 8 ==377== at 0x402FCE: add_string (strarray.c:40) ==377== by 0x4022DB: test_sort_strings (test_source.c:155) ==377== by 0x405F90: srunner_run_all (in /tmc/test/test) ==377== by 0x4028B2: tmc_run_tests (tmc-check.c:122) ==377== by 0x40256A: main (test_source.c:194) ==377== Address 0x518f3e8 is 0 bytes after a block of size 8 alloc'd ==377== at 0x4C245E2: realloc (vg_replace_malloc.c:525) ==377== by 0x402FF4: add_string (strarray.c:43) ==377== by 0x4022DB: test_sort_strings (test_source.c:155) ==377== by 0x405F90: srunner_run_all (in /tmc/test/test) ==377== by 0x4028B2: tmc_run_tests (tmc-check.c:122) ==377== by 0x40256A: main (test_source.c:194) ==377== ==377== Invalid read of size 8 ==377== at 0x402F8D: free_strings (strarray.c:25) ==377== by 0x40246A: test_sort_strings (test_source.c:174) ==377== by 0x405F90: srunner_run_all (in /tmc/test/test) ==377== by 0x4028B2: tmc_run_tests (tmc-check.c:122) ==377== by 0x40256A: main (test_source.c:194) ==377== Address 0x518f6e0 is 0 bytes after a block of size 32 alloc'd ==377== at 0x4C245E2: realloc (vg_replace_malloc.c:525) ==377== by 0x402FF4: add_string (strarray.c:43) ==377== by 0x4022DB: test_sort_strings (test_source.c:155) ==377== by 0x405F90: srunner_run_all (in /tmc/test/test) ==377== by 0x4028B2: tmc_run_tests (tmc-check.c:122) ==377== by 0x40256A: main (test_source.c:194) ==377==
那是因为您没有向数组 add_string()
添加新的 NULL 终止符。因此 add_array()
的后续调用无法在不越界的情况下找到数组的末尾。
我认为你需要重新分配更大的长度:
array = realloc(array, (i + 2) * sizeof(char *));
然后将 NULL 终止符保存到 array[i + 1]
:
array[i + 1] = NULL;
你为什么不尝试使用链表呢?我为每个 add_string()
realloc()
感到难过
这个函数
char **add_string(char **array, const char *string)
{
int i = 0;
while(array[i] != NULL){
i++;
}
array = realloc(array, (i+1) * sizeof(char *));
char *a = malloc(strlen(string)+1);
array[i] = malloc(strlen(string)+1);
strcpy(a, string);
strcpy(array[i], a);
free(a);
return array;
}
错了。它不会向数组中添加一个新槽,您也不会将最后一个元素设置为 NULL。
有效函数看起来像
char **add_string( char **array, const char *string )
{
int i = 0;
while ( array[i++] != NULL );
array = realloc( array, ( i + 1 ) * sizeof( char * ) );
array[i] = NULL;
array[i-1] = malloc( strlen( string ) + 1 );
strcpy( array[i-1], string );
return array;
}
我正在尝试分配一个二维字符串数组,其中最后一个成员始终是 NULL 指针,即空数组由单个 NULL 指针组成。我不断收到 Valgrind 错误,但我不知道为什么。
/*Initializes the string array to contain the initial
* NULL pointer, but nothing else.
* Returns: pointer to the array of strings that has one element
* (that contains NULL)
*/
char **init_array(void)
{
char **array = malloc(sizeof(char *));
array[0] = NULL;
return array;
}
/* Releases the memory used by the strings.
*/
void free_strings(char **array)
{
int i = 0;
while(array[i] != NULL){
free(array[i]);
i++;
}
//free(array[i]);
free(array);
}
/* Add <string> to the end of array <array>.
* Returns: pointer to the array after the string has been added.
*/
char **add_string(char **array, const char *string)
{
int i = 0;
while(array[i] != NULL){
i++;
}
array = realloc(array, (i+1) * sizeof(char *));
char *a = malloc(strlen(string)+1);
array[i] = malloc(strlen(string)+1);
strcpy(a, string);
strcpy(array[i], a);
free(a);
return array;
}
这是 Valgrind 错误:
==375== Invalid read of size 8 ==375== at 0x402FCE: add_string (strarray.c:40) ==375== by 0x401855: test_add_string (test_source.c:58) ==375== by 0x405F90: srunner_run_all (in /tmc/test/test) ==375== by 0x4028B2: tmc_run_tests (tmc-check.c:122) ==375== by 0x40256A: main (test_source.c:194) ==375== Address 0x518df08 is 0 bytes after a block of size 8 alloc'd ==375== at 0x4C245E2: realloc (vg_replace_malloc.c:525) ==375== by 0x402FF4: add_string (strarray.c:43) ==375== by 0x401855: test_add_string (test_source.c:58) ==375== by 0x405F90: srunner_run_all (in /tmc/test/test) ==375== by 0x4028B2: tmc_run_tests (tmc-check.c:122) ==375== by 0x40256A: main (test_source.c:194) ==375== ==375== Invalid read of size 8 ==375== at 0x4018F7: test_add_string (test_source.c:70) ==375== by 0x405F90: srunner_run_all (in /tmc/test/test) ==375== by 0x4028B2: tmc_run_tests (tmc-check.c:122) ==375== by 0x40256A: main (test_source.c:194) ==375== Address 0x518e308 is 0 bytes after a block of size 40 alloc'd ==375== at 0x4C245E2: realloc (vg_replace_malloc.c:525) ==375== by 0x402FF4: add_string (strarray.c:43) ==375== by 0x401855: test_add_string (test_source.c:58) ==375== by 0x405F90: srunner_run_all (in /tmc/test/test) ==375== by 0x4028B2: tmc_run_tests (tmc-check.c:122) ==375== by 0x40256A: main (test_source.c:194) ==375== ==375== Invalid read of size 8 ==375== at 0x402F8D: free_strings (strarray.c:25) ==375== by 0x401AA6: test_add_string (test_source.c:91) ==375== by 0x405F90: srunner_run_all (in /tmc/test/test) ==375== by 0x4028B2: tmc_run_tests (tmc-check.c:122) ==375== by 0x40256A: main (test_source.c:194) ==375== Address 0x518e308 is 0 bytes after a block of size 40 alloc'd ==375== at 0x4C245E2: realloc (vg_replace_malloc.c:525) ==375== by 0x402FF4: add_string (strarray.c:43) ==375== by 0x401855: test_add_string (test_source.c:58) ==375== by 0x405F90: srunner_run_all (in /tmc/test/test) ==375== by 0x4028B2: tmc_run_tests (tmc-check.c:122) ==375== by 0x40256A: main (test_source.c:194) ==375== ==376== Invalid read of size 8 ==376== at 0x402FCE: add_string (strarray.c:40) ==376== by 0x401DCD: test_make_lower (test_source.c:111) ==376== by 0x405F90: srunner_run_all (in /tmc/test/test) ==376== by 0x4028B2: tmc_run_tests (tmc-check.c:122) ==376== by 0x40256A: main (test_source.c:194) ==376== Address 0x518e6d8 is 0 bytes after a block of size 8 alloc'd ==376== at 0x4C245E2: realloc (vg_replace_malloc.c:525) ==376== by 0x402FF4: add_string (strarray.c:43) ==376== by 0x401DCD: test_make_lower (test_source.c:111) ==376== by 0x405F90: srunner_run_all (in /tmc/test/test) ==376== by 0x4028B2: tmc_run_tests (tmc-check.c:122) ==376== by 0x40256A: main (test_source.c:194) ==376== ==376== Invalid read of size 8 ==376== at 0x402F8D: free_strings (strarray.c:25) ==376== by 0x401F5C: test_make_lower (test_source.c:130) ==376== by 0x405F90: srunner_run_all (in /tmc/test/test) ==376== by 0x4028B2: tmc_run_tests (tmc-check.c:122) ==376== by 0x40256A: main (test_source.c:194) ==376== Address 0x518e9d0 is 0 bytes after a block of size 32 alloc'd ==376== at 0x4C245E2: realloc (vg_replace_malloc.c:525) ==376== by 0x402FF4: add_string (strarray.c:43) ==376== by 0x401DCD: test_make_lower (test_source.c:111) ==376== by 0x405F90: srunner_run_all (in /tmc/test/test) ==376== by 0x4028B2: tmc_run_tests (tmc-check.c:122) ==376== by 0x40256A: main (test_source.c:194) ==376== ==377== Invalid read of size 8 ==377== at 0x402FCE: add_string (strarray.c:40) ==377== by 0x4022DB: test_sort_strings (test_source.c:155) ==377== by 0x405F90: srunner_run_all (in /tmc/test/test) ==377== by 0x4028B2: tmc_run_tests (tmc-check.c:122) ==377== by 0x40256A: main (test_source.c:194) ==377== Address 0x518f3e8 is 0 bytes after a block of size 8 alloc'd ==377== at 0x4C245E2: realloc (vg_replace_malloc.c:525) ==377== by 0x402FF4: add_string (strarray.c:43) ==377== by 0x4022DB: test_sort_strings (test_source.c:155) ==377== by 0x405F90: srunner_run_all (in /tmc/test/test) ==377== by 0x4028B2: tmc_run_tests (tmc-check.c:122) ==377== by 0x40256A: main (test_source.c:194) ==377== ==377== Invalid read of size 8 ==377== at 0x402F8D: free_strings (strarray.c:25) ==377== by 0x40246A: test_sort_strings (test_source.c:174) ==377== by 0x405F90: srunner_run_all (in /tmc/test/test) ==377== by 0x4028B2: tmc_run_tests (tmc-check.c:122) ==377== by 0x40256A: main (test_source.c:194) ==377== Address 0x518f6e0 is 0 bytes after a block of size 32 alloc'd ==377== at 0x4C245E2: realloc (vg_replace_malloc.c:525) ==377== by 0x402FF4: add_string (strarray.c:43) ==377== by 0x4022DB: test_sort_strings (test_source.c:155) ==377== by 0x405F90: srunner_run_all (in /tmc/test/test) ==377== by 0x4028B2: tmc_run_tests (tmc-check.c:122) ==377== by 0x40256A: main (test_source.c:194) ==377==
那是因为您没有向数组 add_string()
添加新的 NULL 终止符。因此 add_array()
的后续调用无法在不越界的情况下找到数组的末尾。
我认为你需要重新分配更大的长度:
array = realloc(array, (i + 2) * sizeof(char *));
然后将 NULL 终止符保存到 array[i + 1]
:
array[i + 1] = NULL;
你为什么不尝试使用链表呢?我为每个 add_string()
realloc()
感到难过
这个函数
char **add_string(char **array, const char *string)
{
int i = 0;
while(array[i] != NULL){
i++;
}
array = realloc(array, (i+1) * sizeof(char *));
char *a = malloc(strlen(string)+1);
array[i] = malloc(strlen(string)+1);
strcpy(a, string);
strcpy(array[i], a);
free(a);
return array;
}
错了。它不会向数组中添加一个新槽,您也不会将最后一个元素设置为 NULL。
有效函数看起来像
char **add_string( char **array, const char *string )
{
int i = 0;
while ( array[i++] != NULL );
array = realloc( array, ( i + 1 ) * sizeof( char * ) );
array[i] = NULL;
array[i-1] = malloc( strlen( string ) + 1 );
strcpy( array[i-1], string );
return array;
}