malloc覆盖struct元素

ohh*_*es_ 2 c

在将0分配给count预期之前,先调用malloc 。但是,如果我malloc在给0赋值后调用,count它将覆盖的值countcount每次运行时,我都会打印出一个随机数。

有人可以解释为什么count会被覆盖吗?

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

typedef struct list list;

struct list {
    size_t element_size;
    size_t capacity;
    size_t count;
    void* data;
};

list* create_list(size_t element_size) {
    list* list = malloc(sizeof(list));

    list->element_size = element_size;
    list->capacity = 8;
    list->data = malloc(8 * element_size);
    list->count = 0;

    // If malloc is called here instead then count is overwritten
    // list->data = malloc(8 * element_size);

    printf("count: %zu\n", list->count);

    return list;
}

int main(int argc, char** argv) {
    list* l = create_list(sizeof(int));
}
Run Code Online (Sandbox Code Playgroud)

hyd*_*yde 7

嗯,我认为问题出在这里:

list* list = malloc(sizeof(list));
Run Code Online (Sandbox Code Playgroud)

sizeof(list)给出指针的大小,因为在那一点list是指针,不再是struct类型。因此,您分配的内存太少,并且通过写入未分配的内存来初始化结构数据时会遇到未定义的行为。

通过更改变量或类型名称来修复...或用于sizeof(*list)获取正确的大小。或者,如果您需要我的意见/偏好,请不要typedef与结构一起使用。或其中一些,所以您可能在这里struct list *lst = malloc(sizeof(*lst));


即使使用Undefined Behavior通常效率不高,我们也可以对可能发生的情况进行有根据的猜测:如果malloc在写入超出分配的0值后调用,则malloc创建一个新分配并用其自身的分配数据覆盖0,您将在输出中获得该值。如果以其他方式执行此操作,则写入0将覆盖分配数据。从长远来看,两者都是致命的,因此您可以认为自己很幸运,您注意到了奇怪的输出并尽早发现了UB,而不是后来发生了神秘的崩溃。

  • 绝对建议使用其他名称;即使使用`struct`恶作剧,重用这样的名称也很糟糕(如bug所示!) (3认同)