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

Zig语言ArrayList初始容量异常引发段错误问题求助

问题分析与修复

你的代码核心错误在于返回了栈上临时结构体的指针,导致指针悬空,访问无效内存引发段错误。

错误原因

在C.init函数中,&C{ .list = a }是在函数栈帧中创建的临时结构体,当函数执行完毕返回时,栈帧会被系统回收,这个指针指向的内存区域变成无效垃圾内存。后续访问foo.list时读取到的是随机值,调用append时操作无效内存,最终触发段错误。

修复方案

方案1:直接返回结构体值(推荐,避免堆分配)

不需要返回指针,直接返回C类型的实例,同时补充deinit方法清理ArrayList内存:

const std = @import("std");
const page_allocator = std.heap.page_allocator;
const Allocator = std.mem.Allocator;

const A = struct { e: []const u8 };

const C = struct {
    list: std.ArrayList(A),
    pub fn init(allocator: Allocator) !C {
        var a = try std.ArrayList(A).initCapacity(allocator, 10);
        return C{ .list = a };
    }
    pub fn info(self: *C) void {
        std.log.info("len {}  cap {}", .{ self.list.items.len, self.list.capacity });
    }
    pub fn addElement(self: *C, a: A) !void {
        try self.list.append(a);
    }
    // 补充清理方法,避免内存泄漏
    pub fn deinit(self: *C) void {
        self.list.deinit();
    }
};

test "with arraylist" {
    var foo = try C.init(page_allocator);
    defer foo.deinit(); // 测试结束自动清理
    foo.info();
    try foo.addElement(.{ .e = "bar" });
    foo.info(); // 此时会输出 len 1  cap 10
}

方案2:堆分配结构体实例(需要指针场景)

如果确实需要返回指针,需用分配器在堆上创建C的实例,避免栈内存回收问题:

const std = @import("std");
const page_allocator = std.heap.page_allocator;
const Allocator = std.mem.Allocator;

const A = struct { e: []const u8 };

const C = struct {
    list: std.ArrayList(A),
    pub fn init(allocator: Allocator) !*C {
        // 在堆上分配C实例
        var c = try allocator.create(C);
        // 初始化内部的ArrayList
        c.list = try std.ArrayList(A).initCapacity(allocator, 10);
        return c;
    }
    pub fn info(self: *C) void {
        std.log.info("len {}  cap {}", .{ self.list.items.len, self.list.capacity });
    }
    pub fn addElement(self: *C, a: A) !void {
        try self.list.append(a);
    }
    // 清理堆内存和ArrayList
    pub fn deinit(self: *C, allocator: Allocator) void {
        self.list.deinit();
        allocator.destroy(self);
    }
};

test "with arraylist" {
    var foo = try C.init(page_allocator);
    defer foo.deinit(page_allocator);
    foo.info();
    try foo.addElement(.{ .e = "bar" });
    foo.info();
}

关键注意点

  • Zig中局部变量默认分配在栈上,函数返回后栈内存会被回收,绝对不能返回栈变量的指针。
  • ArrayList使用完必须调用deinit释放内存,否则会造成内存泄漏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 08:05:23