【问题标题】:Adding strings to an array of strings is somehow changing the previous strings in the array将字符串添加到字符串数组会以某种方式更改数组中的先前字符串
【发布时间】:2015-10-05 07:11:43
【问题描述】:

我编写了这个函数,旨在将字符串添加到字符串数组中,每次在将新字符串放入之前为新字符串创建足够的内存,并且reallocing 当数组已满时,它的大小。这是我的代码示例:

#define INITIAL 10

int addtoarray(char **A, int *size, int n, char *b);

int
main(int argc, char **argv) {
    char **D, a[3]="ab"; /*'a' is arbitrary for this example */
    int n=0, size=INITIAL, i, j;

    D = (char**)malloc(INITIAL*sizeof(char));

    for (i=0; i<3; i++) {
        n = addtoarray(D, &size, n, a);

        /* print the contents of D */
        printf("Dict: ");
        for (j=0; j<n; j++) {
            printf("D[%d]='%s' ", j, D[j]);    
        } printf("\n");
    }

    return 0;
}

int
addtoarray(char **A, int *size, int n, char *b) {

    if (*size == n) {
        /* Array is full, give more space */ 
        realloc(A, *size = 2*(*size));
        assert(A);
    }

    printf("Adding '%s' to D[%d], size of D = %d\n", b, n, *size);

    /* Create space in array for new string */
    A[n] = (char*)malloc(strlen(b)+1);
    assert(A[n]);

    /* Put the new string in array! */
    strcpy(A[n], b);
    n++;

    return n;
}

在本例中,'n' 是数组中的字符串数。这段代码的输出是:

Adding 'ab' to D[0], size of D = 10
D: D[0]='ab' 
Adding 'ab' to D[1], size of D = 10
D: D[0]='ab' D[1]='ab' 
Adding 'ab' to D[2], size of D = 10
D: D[0]='?K@S?' D[1]='ab' D[2]='ab'

正如您所看到的,第三次调用该函数时,字符串很好地进入了数组。但是数组中的第一个字符串以某种方式发生了变化。我不知道为什么会发生这种情况,但我很确定它发生在函数的A[n] = (char*)malloc(strlen(b)+1); 行上。

有人知道我做错了什么吗? (另外,如果您对我的代码的其他部分有任何提示)

【问题讨论】:

  • 这个:realloc(A, *size = 2*(*size)); 至少需要为A = realloc(A, *size = 2*(*size));;分配可以在realloc() 之后移动。之后的断言是一种俗气(且危险)的错误处理机制,如果您在“生产”代码中禁用断言,则更是如此。仅当您使用将在运行时用于验证重新分配的实际 if 进行备份时,您才可以使用 assert()
  • 需要查看realloc的返回值。当你到达它时,这就是你的新内存地址将被返回的地方。这不是这个问题,但我想我会提到它。添加正确的包含后,您的代码在此处运行良好。
  • 在这个阶段,我刚刚被告知使用断言来确保 malloc 或 realloc 没有返回空指针。你会推荐更像 if (!ptr) {printf("Malloc failed\n");exit(EXIT_FAILURE);} 其中 ptr 是 malloc 的 realloc 返回的指针吗?
  • 这样的显式测试,是的。如果您要退出错误,那么我宁愿调用一个函数,该函数在标准错误(不是标准输出)上打印错误并退出。如果您要返回,则不能使用ptr = realloc(per, new size); 成语。你必须使用:void *newptr = realloc(oldster, new size);,否则你会泄露内存。

标签: c arrays string malloc dynamic-arrays


【解决方案1】:

如果你想要一个字符串数组,你需要char *大小的空间:

malloc(INITIAL*sizeof(char));

应该是

malloc(INITIAL*sizeof(char *));

realloc 部分:

realloc(A, *size = 2*(*size));

正如 Jonathan Leffler 所指出的,realloc 返回一个指向重新分配的内存块的指针,您需要一个三重指针来传递(并使用解引用运算符操作其值)一个指向字符串的指针:

int addtoarray(char ***A, int *size, int n, char *b) {
   ...
   *A = realloc(*A, (*size = 2*(*size)) * sizeof(char *));
   assert(*A);
   ...

在您的 main 函数中:

n = addtoarray(&D, &size, n, a);

【讨论】:

  • 好吧,部分......代码还必须捕获realloc()的结果;原来的指针不再有效,只有返回的新指针仍然有效。
  • 您能解释一下使用三重指针的原因吗?我不确定我是否完全理解。
  • @SirBarkalot,您需要一个三重指针来更改函数内双指针的地址,或者您可以返回新的重新分配的指针并将指针传递给n
【解决方案2】:

这是因为您没有分配从 realloc 返回的指针。

realloc(A, *size = 2*(*size));

应该是:

A = realloc(A, *size = 2*(*size));

没有这个,A 仍然指向旧的内存空间。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-12-15
    • 1970-01-01
    • 2023-01-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-15
    相关资源
    最近更新 更多