【问题标题】:Data being corrupted when using realloc()使用 realloc() 时数据损坏
【发布时间】:2021-02-01 01:56:36
【问题描述】:

在一个类项目中,我需要增加 void 指针的动态数组的容量。目前我在使用 realloc 时遇到了损坏用户数据的问题。

void dynarray_insert(struct dynarray* da, void* val) {
    int i;
    int size = da->size;
    int cap = da->capacity;


    /*if there is no more room*/
    if (size == cap) {
        cap = cap * 2;                  /*double capacity*/
        void** temp = realloc(da, sizeof(void*) * cap);

        da->data = temp;
    }

    /*if there is room*/
    else if (size < cap) {
        da->data[size] = val;
    }

    size++;

    da->size = size;
    da->capacity = cap;

  return;
}

有我目前的增容功能代码,

struct dynarray {
  void** data;
  int size;
  int capacity;
};

这是 dynarray 结构。

编辑:现在我修复了 realloc 的目标,我有一个来自 realloc 的内存泄漏。

==474== HEAP SUMMARY:
==474==     in use at exit: 64 bytes in 1 blocks
==474==   total heap usage: 15 allocs, 14 frees, 848 bytes allocated
==474==
==474== 64 bytes in 1 blocks are definitely lost in loss record 1 of 1
==474==    at 0x483DFAF: realloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==474==    by 0x1098E3: dynarray_insert (dynarray.c:96)
==474==    by 0x109303: test_dynarray (test_dynarray.c:39)
==474==    by 0x1097B6: main (test_dynarray.c:136)
==474==
==474== LEAK SUMMARY:
==474==    definitely lost: 64 bytes in 1 blocks
==474==    indirectly lost: 0 bytes in 0 blocks
==474==      possibly lost: 0 bytes in 0 blocks
==474==    still reachable: 0 bytes in 0 blocks
==474==         suppressed: 0 bytes in 0 blocks

任何想法可能来自哪里?

【问题讨论】:

  • 如果realloc(da, sizeof(void*) * cap); 成功,则不再允许您访问da - 因此下一行(da-&gt;data = temp;)调用未定义行为。虽然这部分代码看起来很奇怪,但你想在这里做什么?
  • 第二次看我怀疑你想realloac(da-&gt;data 而不是da

标签: c malloc dynamic-arrays realloc


【解决方案1】:

有多个问题:

  • 您没有重新分配元素数组,而是 dynarray 结构本身。
  • 如果重新分配数组,则不会存储元素:如果像您那样分隔 else 子句,则很容易出错。
  • 您不检查 0 初始容量:cap * 2 仍将是 0

这是修改后的版本:

#include <stdlib.h>

struct dynarray {
    void **data;
    int size;
    int capacity;
};

int dynarray_insert(struct dynarray *da, void *val) {
    int size = da->size;
    int cap = da->capacity;

    if (size == cap) {            /* if there is no more room */
        cap = cap ? cap * 2 : 8;  /* double capacity, special case for zero */
        void **temp = realloc(da->data, sizeof(void *) * cap);
        if (temp == NULL) {
            return -1;   /* return -1 upon realloc failure */
        }
        da->cap = cap;
        da->data = temp;
    }
    da->data[size] = val;
    return da->size++;   /* return the index of the new element if successful */
}

【讨论】:

  • 感谢您的快速响应。我已经修复了重新分配数组和 else 子句的问题。在分配的约束内,我无法更改函数的返回类型。这让它工作,但现在我有一个内存泄漏。 Gdb 说它来自 realloc。另外,你能解释一下吗: cap = cap ?上限 * 2:8;问号运算符在这里做什么?
  • @JulianGilmour:三元运算符等价于if (cap != 0) { cap = cap * 2; } else { cap = 8; }。释放dynarray 结构的函数中可能存在内存泄漏:如果分配了da-&gt;datada,则必须释放它本身。您应该发布完整的程序。
  • 最后,内存泄漏来自于尝试释放 dynarray->data 中的每个单独的 void 指针,而不是分配给 dynarray->data 的整个内存块。
  • @JulianGilmour:确实,您必须定义动态数组中各个指针的生命周期,要么在释放 dynarray 结构时必须释放所有指针,要么不释放,并且必须在别处处理它们。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-30
  • 2019-05-23
  • 1970-01-01
  • 1970-01-01
  • 2011-10-02
相关资源
最近更新 更多