【问题标题】:Why free(): invalid next size (fast)为什么 free():下一个尺寸无效(快速)
【发布时间】:2013-10-19 19:44:13
【问题描述】:

请查看 c 代码并帮助我。为什么我有“free(): invalid next size (fast)”?我尝试了 valgrind,但不明白,有太多“无效的写入/读取 ....”,但如果我评论 free_array(all) a 有正确的答案。它只是所有代码的一部分。

#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
#include <stdlib.h>

struct pair {
    uint32_t num;
    uint32_t effect;
};

struct array {
    size_t size;
    struct pair data[];
};

size_t sizeof_array(size_t size)
{
    return sizeof(struct array) + (size * sizeof(uint32_t));
}

struct pair *create_pair(uint32_t i, uint32_t eff)
{
    struct pair *ret = calloc(2, sizeof(uint32_t));
    if (! ret)
        abort();
    ret->num = i;
    ret->effect = eff;
    return ret;
}

struct array *create_array(size_t size)
{
    struct array *ret = calloc(1, sizeof_array(size));
    if (! ret) 
        abort();
    ret->size = size;
    return ret;
}

void free_array(struct array *array)
{
//    size_t i;
//    for (i = 0; i < array->size; ++i) {
//        free(&array->data[i]);
//    }
    free(array);
}

int main()
    {
    int eff;
    size_t n;
    scanf("%zu", &n);
    struct array *all = create_array(n);
    size_t i;
    for(i = 0; i < n; ++i) {
        scanf("%d", &eff);
        all->data[i] = *create_pair(i, eff);
    }

    free_array(all);
    return 0;
}

【问题讨论】:

  • calloc(2, sizeof(uint32_t)); -> calloc(1, sizeof *ret) 为了安全起见。您永远无法知道对齐的位置(以及多少)。
  • 如果你为一个结构分配内存,使用那个结构作为分配的基础(我说的是你的create_pair函数,你分配给uint32_t而不是一个struct pair )。

标签: c memory struct g++ free


【解决方案1】:

就像我在评论中所说的,在分配内存时不要使用结构中每个成员的大小作为基础,使用实际的结构。这是您的问题的原因,因为您的函数 sizeof_array 返回的大小大约是您需要的大小的一半。

相反,它应该看起来像

size_t sizeof_array(size_t size)
{
    return sizeof(struct array) + (size * sizeof(struct pair));
    /* Notice the use of the structure instead   ^^^^^^^^^^^ */
}

由于sizeof_array 返回的大小太小,您分配的内存太少并且写入超出了分配的内存范围,然后以未定义的行为结束


您也有内存泄漏,因为您为数组中的每个struct pair 分配内存。当您分配 array 结构时,您已经为每个 pair 分配了内存,无需逐个分配,尤其是因为您只是丢弃了指针,因此存在内存泄漏。

释放时,只需释放 array 结构,因为这就是您(应该)分配的全部内容。

【讨论】:

  • 谢谢,你说得对!现在我没有“free():invalid next size”并通过了前 9 次测试)现在我在 10 次测试中有未知的 RE 错误,但我看不到测试输入(
  • 在 free_array 函数中我应该释放循环中的每个结构对还是 free(array) 就足够了?
  • @r.z 更新了我的答案。
【解决方案2】:

Joachim 给出了正确的答案,但原始“sizeof_array()”不正确的原因是“struct array”包含“struct pair”而不是“uint32_t”的数组。并且结构体是“sizeof(uint32_t)”的两倍。

此外,虽然不太可能,但某些平台上的编译器可能会在“结构对”中添加额外的对齐空间。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-28
    • 1970-01-01
    • 2014-07-01
    相关资源
    最近更新 更多