为什么free():下一个大小无效(快)

时间:2013-10-19 19:44:14

标签: c memory struct g++ free

请查看c代码并帮助我。为什么我有“免费():无效的下一个大小(快)”?我尝试valgrind,但不明白,有太多“无效的写/读....”,但如果我评论free_array(全部)一个有正确的答案。它只是所有代码的一部分。

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

2 个答案:

答案 0 :(得分: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结构,就像你应该分配的一样。

答案 1 :(得分:0)

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

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