【问题标题】:Manipulating pointers causes "invalid realloc()" in valgrind操作指针会导致 valgrind 中的“无效 realloc()”
【发布时间】:2020-08-20 15:23:00
【问题描述】:

我有一个项目,该项目涉及读取不确定数量的字符串,并根据一些关联的元数据将它们附加到不同的 char** 中。我的代码将 realloc() 一个 char** 与数据一起动态增长,并且它将指向其中一个 char** 的指针作为输入,因此它可能有点通用。但是,我搞砸了导致 realloc() 过早释放 char** 的指针,从而导致错误。我找不到我做错了什么。

这是一个精简的示例,说明了我正在尝试做的事情。对元数据的引用被删除,代码在一个 char** 和另一个 char** 之间交替,这种方式可能在整个项目中发生。此示例还省略了对 malloc() 的一些错误检查和一些将在整个项目中出现的适当清理(即 free())。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void print_elems(char **array, int length) {
    for (int i = 0; i < length; i++) {
        printf("%s", array[i]);
    }
}

void main() {

    char **array = (char**) malloc(sizeof(char*));
    int length = 1;
    int index = 0;
    char **array2 = (char**) malloc(sizeof(char*));
    int length2 = 1;
    int index2 = 0;


    char **pointarray = array2;
    int* pointlen = &length2;
    int* pointidx = &index2;

    char newelem[10];
    while(1) {
        printf("Enter a string: ");
        fgets(newelem, 10, stdin);

        pointarray = (pointarray == array2 ? array : array2);
        pointlen = (pointlen == &length2 ? &length : &length2);
        pointidx = (pointidx == &index2 ? &index : &index2);

        if (*pointlen == *pointidx) {
            printf("Resizing array...\n");
            void* newarray = realloc(pointarray, sizeof(char*)*(*pointlen+1));
            if (pointarray == NULL) {
                perror("Error allocating memory.\n");
                exit(1);
            } else {
                pointarray = (char**) newarray;
            }
            (*pointlen)++;
        }

        pointarray[*pointidx] = strdup(newelem);
        (*pointidx)++;

        print_elems(pointarray, *pointlen);
    }

}

通常在循环运行不超过 10 次后,程序就会崩溃。 Valgrind 给出这个输出:

==11278== Invalid free() / delete / delete[] / realloc()
==11278==    at 0x483AD19: realloc (vg_replace_malloc.c:836)
==11278==    by 0x4012EA: main (test.c:38)
==11278==  Address 0x4a23090 is 0 bytes inside a block of size 8 free'd
==11278==    at 0x483AD19: realloc (vg_replace_malloc.c:836)
==11278==    by 0x4012EA: main (test.c:38)
==11278==  Block was alloc'd at
==11278==    at 0x483880B: malloc (vg_replace_malloc.c:309)
==11278==    by 0x401215: main (test.c:17)
==11278== 
==11278== Invalid write of size 8
==11278==    at 0x401345: main (test.c:48)
==11278==  Address 0x10 is not stack'd, malloc'd or (recently) free'd

如果我不做所有这些指针切换,程序运行良好,但项目会复杂得多,我必须想象有一种方法可以做我想做的事情。

谁能告诉我是什么让 realloc() 出轨了?

【问题讨论】:

  • 欢迎来到 Stack Overflow! dont cast malloc
  • 为什么有两个列表?分配给pointarraypointlenpointidx 的具体任务是什么?
  • @dbush 他显然试图将备用输入放入每个数组中,使用间接在它们之间切换。
  • @Barmar 我明白了,问题是选择每一个的标准是什么?
  • 我没有看到任何标准,它只是来回走动。

标签: c pointers valgrind realloc


【解决方案1】:

调用realloc() 后,您将结果分配给pointarray,但这不会改变arrayarray2。然后在未来的迭代中,您将其中一个分配给pointarray,但它们不再指向有效存储。

您需要一个额外的间接级别,类似于您间接获取长度和索引变量的方式。

此外,在您调用realloc() 后,您正在检查pointarray,但您应该检查newarray

void main() {

    char **array = malloc(sizeof(char*));
    int length = 1;
    int index = 0;
    char **array2 = malloc(sizeof(char*));
    int length2 = 1;
    int index2 = 0;

    char ***pointarray = array2;
    int* pointlen = &length2;
    int* pointidx = &index2;

    char newelem[10];
    while(1) {
        printf("Enter a string: ");
        fgets(newelem, 10, stdin);

        pointarray = (pointarray == &array2 ? &array : &array2);
        pointlen = (pointlen == &length2 ? &length : &length2);
        pointidx = (pointidx == &index2 ? &index : &index2);

        if (*pointlen == *pointidx) {
            printf("Resizing array...\n");
            void* newarray = realloc(*pointarray, sizeof(char*)*(*pointlen+1));
            if (newarray == NULL) {
                perror("Error allocating memory.\n");
                exit(1);
            } else {
                *pointarray = newarray;
            }
            (*pointlen)++;
        }
        (*pointarray)[*pointidx] = strdup(newelem);
        (*pointidx)++;

        print_elems(*pointarray, *pointlen);
    }
}

【讨论】:

  • 谢谢 - 这提供了一些帮助,但不起作用。它在与“realloc():无效指针”的第三次交互中崩溃
  • 从头开始 - 我的代码有错误。它确实有效。感谢您的帮助,以及关于 malloc() 的指针!
猜你喜欢
  • 2015-07-13
  • 1970-01-01
  • 2021-04-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-21
  • 2017-09-16
  • 1970-01-01
相关资源
最近更新 更多