You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言如何正确初始化struct?局部struct对象赋值指针出现内存错误

问题根本原因

你遇到的问题是典型的栈对象生命周期越界问题,C语言里局部自动变量(函数内不加特殊修饰的普通变量)的生命周期仅覆盖它所在的代码块:

  • 在list_init的for循环内定义的struct list list是分配在函数栈帧上的临时对象,每轮循环结束后,本轮的list对象就会被销毁,它占用的栈内存会被后续操作覆盖
  • 你把&list(临时对象的栈地址)赋值给lists[i],等list_init函数执行完返回后,整个函数的栈帧都会被回收,所有lists数组里存的指针全都是野指针,访问这些指针指向的内存就是非法的,所以会读到随机的size值
  • 换成malloc分配struct的方式之所以正常,是因为malloc分配的内存在堆上,生命周期不受函数栈帧影响,只要你不主动free就一直有效

直接使用struct对象的实现方式

如果你不想给每个struct实例单独malloc,可以直接把lists数组定义为struct对象数组,而非struct指针数组,修改方法如下:

1. 调整list_init函数逻辑

把list_init的入参改成struct list* lists(指向struct对象数组的首地址),直接给数组里的每个元素赋值即可,不需要存指针:

void list_init(struct list* lists, size_t len, size_t list_len) {
    for (size_t i = 0; i < len; i++) {
        // 直接给数组中已存在的struct对象赋值,用calloc直接初始化值为0,符合你预期的输出
        lists[i].values = calloc(list_len, sizeof(int));
        lists[i].size = list_len;
    }
}

2. 调整main函数逻辑

把lists定义为struct对象数组,而非指针数组,成员访问改用.运算符即可:

// 注意标准C的main返回值是int,void main属于非标准写法
int main() {
    int len = 3;
    struct list lists[len]; // 直接定义struct对象数组,内存已经在栈上分配完成
    list_init(lists, len, 5);

    // 打印逻辑
    for (size_t i = 0; i < len; i++) {
        printf("list %zu: ", i);
        printf("size: %zu\n", lists[i].size);
        for (size_t j = 0; j < lists[i].size; j++) {
            printf("%d ", lists[i].values[j]);
        }
        printf("\n");
    }

    // 不要忘了释放每个values申请的堆内存,避免泄漏
    for (size_t i = 0; i < len; i++) {
        free(lists[i].values);
    }
    return 0;
}

这种方式下struct对象的内存是在main函数的栈帧上分配的,生命周期和main函数一致,只要在main的作用域内访问都是合法的,不需要单独malloc每个struct实例。

内容的提问来源于stack exchange,提问作者JolonB

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 14:18:03