简体   繁体   English

C-字符串数组和神秘的Valgrind错误

[英]C - Array of Strings & Mysterious Valgrind Error

I'm trying to allocate a two-dimensional array of strings, where the last member is always a NULL pointer, ie an empty array consists of a single NULL pointer. 我正在尝试分配一个二维字符串数组,其中最后一个成员始终是NULL指针,即,一个空数组由一个NULL指针组成。 I keep getting Valgrind errors but I have no idea why. 我不断收到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;
}

Here's the Valgrind error: 这是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 == 375 ==大小为8的无效读取== 375 ==在0x402FCE:add_string(strarray.c:40)== 375 ==由0x401855:test_add_string(test_source.c:58)== 375 ==由0x405F90: srunner_run_all(在/ tmc / test / test中)== 375 ==通过0x4028B2:tmc_run_tests(tmc-check.c:122)== 375 ==通过0x40256A:main(test_source.c:194)== 375 ==地址0x518df08是大小为8的块之后的0字节== 375 ==在0x4C245E2:重新分配(vg_replace_malloc.c:525)== 375 ==通过0x402FF4:add_string(strarray.c:43)== 375 ==通过0x401855:test_add_string(test_source.c:58)== 375 ==通过0x405F90:srunner_run_all(在/ tmc / test / test中)== 375 ==通过0x4028B2:tmc_run_tests(tmc-check.c:122)== 375 == by 0x40256A:main(test_source.c:194)== 375 == == 375 ==大小为8的无效读取== 375 ==在0x4018F7:test_add_string(test_source.c:70)== 375 ==通过0x405F90:srunner_run_all(在/ tmc / test / test中)== 375 ==通过0x4028B2:tmc_run_tests(tmc-check.c:122)== 375 ==通过0x40256A:主(test_source.c:194)== 375 = =地址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) ==37 在大小为40的块之后的0字节== 375 ==在0x4C245E2:重新分配(vg_replace_malloc.c:525)== 375 ==通过0x402FF4:add_string(strarray.c:43)== 375 ==通过0x401855:test_add_string(test_source.c:58)== 375 ==通过0x405F90:srunner_run_all(在/ tmc / test / test中)== 375 ==通过0x4028B2:tmc_run_tests(tmc-check.c:122)== 375 = =通过0x40256A:主(test_source.c:194)== 375 == == 375 ==无效的8号读取== 375 ==在0x402F8D:free_strings(strarray.c:25)== 375 ==通过0x401AA6 :test_add_string(test_source.c:91)== 375 ==通过0x405F90:srunner_run_all(在/ tmc / test / test中)== 375 ==通过0x4028B2:tmc_run_tests(tmc-check.c:122)== 375 ==通过0x40256A:main(test_source.c:194)== 375 ==地址0x518e308是大小为40的块之后的0个字节alloc = d == 375 ==在0x4C245E2:重新分配(vg_replace_malloc.c:525)== 375 = =通过0x402FF4:add_string(strarray.c:43)== 375 ==通过0x401855:test_add_string(test_source.c:58)== 375 ==通过0x405F90:srunner_run_all(在/ tmc / test / test中)== 37 5== 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: s 5 ==通过0x4028B2:tmc_run_tests(tmc-check.c:122)== 375 ==通过0x40256A:main(test_source.c:194)== 375 == == 376 ==大小8的无效读取== 376 ==在0x402FCE:add_string(strarray.c:40)== 376 ==通过0x401DCD:test_make_lower(test_source.c:111)== 376 ==通过0x405F90:srunner_run_all(在/ tmc / test / test中)== 376 ==通过0x4028B2:tmc_run_tests(tmc-check.c:122)== 376 ==通过0x40256A:main(test_source.c:194)== 376 ==地址0x518e6d8是分配了大小为8的块后的0字节== 376 ==在0x4C245E2:重新分配(vg_replace_malloc.c:525)== 376 ==通过0x402FF4:add_string(strarray.c:43)== 376 ==通过0x401DCD:test_make_lower(test_source.c:111)== 376 ==通过0x405F90:srunner_run_all(在/ tmc / test / test中)== 376 ==通过0x4028B2:tmc_run_tests(tmc-check.c:122)== 376 ==通过0x40256A:main(test_source.c:194) == 376 == == 376 ==大小为8的无效读取== 376 ==在0x402F8D:free_strings(strarray.c:25)== 376 ==由0x401F5C:test_make_lower(test_source.c:130)== 376 ==通过0x405F90:s runner_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== Runner_run_all(在/ tmc / test / test中)== 376 ==通过0x4028B2:tmc_run_tests(tmc-check.c:122)== 376 ==通过0x40256A:main(test_source.c:194)== 376 ==地址0x518e9d0是位于大小为32的块之后的0字节== 376 ==在0x4C245E2:重新分配(vg_replace_malloc.c:525)== 376 ==通过0x402FF4:add_string(strarray.c:43)== 376 ==通过0x401DCD:test_make_lower(test_source.c:111)== 376 ==通过0x405F90:srunner_run_all(在/ tmc / test / test中)== 376 ==通过0x4028B2:tmc_run_tests(tmc-check.c:122)== 376 == by 0x40256A:main(test_source.c:194)== 376 == == 377 ==大小为8的无效读取== 377 == at 0x402FCE:add_string(strarray.c:40)== 377 == by 0x4022DB:test_sort_strings(test_source.c:155)== 377 ==通过0x405F90:srunner_run_all(在/ tmc / test / test中)== 377 ==通过0x4028B2:tmc_run_tests(tmc-check.c:122)== 377 = = by 0x40256A:main(test_source.c:194)== 377 ==地址0x518f3e8是大小为8的块之后的0个字节alloc'd == 377 ==在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) = 通过0x402FF4:add_string(strarray.c:43)== 377 ==通过0x4022DB:test_sort_strings(test_source.c:155)== 377 ==通过0x405F90:srunner_run_all(在/ tmc / test / test中)== 377 ==通过0x4028B2:tmc_run_tests(tmc-check.c:122)== 377 ==通过0x40256A:main(test_source.c:194)== 377 == == 377 ==大小8的无效读取== 377 == 0x402F8D:free_strings(strarray.c:25)== 377 ==通过0x40246A:test_sort_strings(test_source.c:174)== 377 ==通过0x405F90:srunner_run_all(在/ tmc / test / test中)== 377 ==通过0x4028B2:tmc_run_tests(tmc-check.c:122)== 377 ==通过0x40256A:main(test_source.c:194)== 377 ==地址0x518f6e0是大小为32的块分配后的0字节== 377 ==在0x4C245E2:重新分配(vg_replace_malloc.c:525)== 377 ==通过0x402FF4:add_string(strarray.c:43)== 377 ==通过0x4022DB:test_sort_strings(test_source.c:155)== 377 ==通过0x405F90:srunner_run_all(在/ tmc / test / test中)== 377 ==通过0x4028B2:tmc_run_tests(tmc-check.c:122)== 377 ==通过0x40256A:主(test_source.c:194)= =377== = 377 ==

That's because you didn't add new NULL-terminator to the array add_string() . 那是因为您没有向数组add_string()添加新的NULL终止符。 So subsequent calls of add_array() fail to find end of array without going out of bounds. 因此,随后对add_array()调用无法找到数组的结尾而不会超出范围。

I think you need realloc with larger length: 我认为您需要重新分配更大的长度:

array = realloc(array, (i + 2) * sizeof(char *));

And then save NULL-terminator to array[i + 1] : 然后将NULL终止符保存到array[i + 1]

array[i + 1] = NULL;

Why didn't you try using linked lists for that? 您为什么不尝试使用链接列表呢? I feel bad for realloc() per each add_string() 我为每个add_string() realloc()感到add_string()

This function 该功能

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;
}

is wrong. 是错的。 It does not add a new slot into the array and you do not set the last element to NULL. 它不会在阵列中添加新的插槽,并且您不会将最后一个元素设置为NULL。

The valid function can look like 有效功能可能看起来像

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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM