【问题标题】:C - Array of Strings & Mysterious Valgrind ErrorC - 字符串数组和神秘的 Valgrind 错误
【发布时间】:2015-03-14 09:20:11
【问题描述】:

我正在尝试分配一个二维字符串数组,其中最后一个成员始终是一个 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== 大小为 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个字节== 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==    通过 0x40256A: main (test_source.c:194) ==375==  ==375== 无效 读取 大小 8 ==375==    在 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==  地址 0x518e在 0x4C245E2 处分配大小为 40 的块后,308 为 0 字节 ==375==    在 0x4C245E2:realloc (vg_replace_malloc.c:525) ==375==    通过 0x402FF4:add_string (strarray.c:43) ==375== 0x401855:test_add_string(test_source.c:58)== 375 == by 0x405f90:srunner_run_all(/ tmc / test / test)== 375 == by 0x4028b2:tmc_run_tests(tmc-check.c:122)== 375 == by 0x40256a:main(test_source.c:194)== 375 == == 375 ==无效读取大小8 == 375 ==在0x402f8d:free_strings(strarray.c:25)== 375 == by 0x401AA6: test_add_string (test_source.c:91) ==375==    0x405F90: srunner_run_all (in /tmc/test/test) ==375==      0x4028B2: tmc_run_tests (tmc-check.c:122) ==375= =×0x40256A:main(test_source.c:194)== 375 ==地址0x518e308在0x4c245e2的块块块之后是0字节: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(/ tmc / test / test)= =375==    0x4028B2: tmc_run_tests (tmc-check.c:122) ==375==     0x40256A:   (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 (in /tmc/test/test) == 376==    0x4028B2: tmc_run_tests (tmc-check.c:122) ==376==     0x40256A:  (test_source.c:194) ==376== 地址 0x518e6d8 是 0 字节 在 8 alloc 大小的块之后' d == 376 ==在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(/ tmc / test / test)== 376 == by 0x4028b2:tmc_run_tests(tmc-check.c:122)== 376 == by 0x40256a:main(test_source.c:194 )== 376 == == 376 ==读取大小8 == 376 ==在0x402f8d:free_strings(strarray.c:25)== 376 == by 0x401f5c:test_make_lower(test_source.c:130)== 376==    由 0x405F90 : srunner_run_all (in /tmc/test/test) ==376==    0x4028B2: tmc_run_tests (tmc-check.c:122) ==376==      0x40256A: 主 (test_source.c:194) ==376==地址 0x518e9d0 在 0x4C245E2 处分配的大小为 32 的块之后为 0 字节 ==376==    在 0x4C245E2:realloc (vg_replace_malloc.c:525) ==376==    通过 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==    0x40256A: main (test_source.c:194) ==376==  ==377== 大小为 8 的读取无效 ==377==    在 0x402FCE: add_string (strarray.c:40) ==377==乘0x4022db:test_sort_strings(test_source.c:155)== 377 == by 0x405f90:srunner_run_all(/ tmc / test / test)== 377 == by 0x4028b2:tmc_run_tests(tmc-check.c:122)== 377 ==    通过 0x40256A: main (test_source.c:194) ==377==  地址 0x518f3e8 在大小为 8 分配的块之后  0 字节 ==377==    在 0x4C245E2: realloc (vg_replace_malloc.c:525) == 37 7 == 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==    0x4028B2: tmc_run_tests (tmc-check.c:122) ==377==     0x40256A: 主 (test_source.c:194) ==377==  ==377== 8 大小无效读取 ==377 ==    在 0x402F8D: free_strings (strarray.c:25) ==377==    by 0x40246A: test_sort_strings (test_source.c:174) ==377==         0x405F90: srunner_run_all (in /tmc/test/test) ==377 ==     by 0x4028B2: tmc_run_tests (tmc-check.c:122) ==377==        0x40256A: 主 (test_source.c:194) ==377==  地址 0x518f6e0 是 0 字节 在 32 alloc'd 大小的块之后==377==    在 0x4C245E2: realloc (vg_replace_malloc.c:525) ==377==    通过 0x402FF4: add_string (strarray.c:43) ==377==    通过 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==

【问题讨论】:

  • OT: malloc()a 然后 free() 在三行之后对我来说似乎没用。不需要a

标签: c arrays string valgrind


【解决方案1】:

那是因为您没有将新的 NULL 终止符添加到数组 add_string()。所以add_array()的后续调用无法找到数组的结尾而不超出边界。

我认为你需要更大长度的 realloc:

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

然后将NULL终止符保存到array[i + 1]:

array[i + 1] = NULL;

您为什么不尝试使用链表呢?我为每个add_string()realloc() 感到难过

【讨论】:

  • 因为add_string i 不是数组的长度,而是最后一个元素的索引。所以:i - 插入字符串的索引,i + 1 - NULL 的索引,i + 2 - 数组的长度。
【解决方案2】:

这个函数

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

【讨论】:

  • 更好,我总是对与idx-1idx+1 不同的所有内容感到困惑。但是size_t 呢? ;-)
  • @alk 在这种情况下 size_t 看起来更好。
猜你喜欢
  • 2011-11-19
  • 2020-08-25
  • 1970-01-01
  • 2012-12-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-07
  • 2015-03-13
相关资源
最近更新 更多