使用Zig的arena.allocator创建联合体指针时触发段错误
Zig ArenaAllocator 结合使用时的段错误问题解决
你提供的代码在调用createExpressionNode时触发段错误,核心原因是Parser.init函数中错误处理了ArenaAllocator的生命周期:
- 在
Parser.init里,你创建了一个栈上的arena局部变量,随后将其赋值给Parser的.arena字段。 - 当
init函数返回时,栈上的局部arena会被Zig自动调用deinit清理,导致Parser中存储的arena实例彻底失效。 - 你存在Parser里的
.allocator是从这个已失效的arena获取的,后续调用allocator.create时,访问的是已释放的内存区域,直接触发段错误。这也是为什么创建u8指针同样出错——问题根源在分配器本身,和具体分配类型无关。
以下是修复后的完整代码:
const std = @import("std"); pub const NumberExpression = struct { value: f64, }; pub const ExprTypes = enum { number_expr, }; pub const Expression = union(ExprTypes) { number_expr: NumberExpression, }; pub const Parser = struct { allocator: std.mem.Allocator, arena: std.heap.ArenaAllocator, // 正确初始化Parser,让实例直接持有有效的ArenaAllocator pub fn init(allocator: std.mem.Allocator) Parser { var parser = Parser{ .arena = std.heap.ArenaAllocator.init(allocator), .allocator = undefined, }; // 从Parser自身持有的arena获取分配器 parser.allocator = parser.arena.allocator(); return parser; } // 添加deinit方法,遵循Zig内存管理规范清理arena pub fn deinit(self: *Parser) void { self.arena.deinit(); } pub fn createExpressionNode(self: *Parser) ?*Expression { const expr = self.allocator.create(Expression) catch |err| { std.debug.print("Error when trying to create AST expression nodes: {any}\n", .{err}); return null; }; return expr; } }; pub fn main() !void { var p = Parser.init(std.heap.page_allocator); // 使用defer确保arena被正确清理 defer p.deinit(); _ = p.createExpressionNode(); }
内容的提问来源于stack exchange,提问作者fabinho
相关产品推荐
相关产品推荐

