Having trouble understanding growing arrays/slices and pointers

Hi Friends,

I’m working on a parser in Zig, but I’m having trouble understanding the lifecycles of growing arrays.

I’m making a list of tokens that’s being stored in a Lexer, As I scan source code I add a token to an array of tokens ArrayList(Tokens). I have a Lexer struct that holds this array of tokens:

pub const Token = struct {
	type: Type,
	start: usize,
	length: usize,
	line: usize,
	pub const Type = enum { letter, number, symbol, };
};

const Tokens = ArrayList(Token);

pub const Lexer = struct {
	source: []const u8,
	start: usize = 0,
	current: usize = 0,
	line: usize = 1,
	tokens: *Tokens,
	
	const Self = @This();

	pub fn init(allocator: Allocator, source: []const u8) !Lexer {
		var arr = Tokens.init(allocator);
		return .{
			.source = source,
			.tokens = &arr,
		};
	}
};

I’m sure that I’m not understanding memory correctly and my pointers are wrong or something. But I’m not sure how. I would love some help.

-kow

&arr is a pointer to stack-allocated memory that goes out of scope when Lexer.init returns.

The simplest way to fix this would be to not use a pointer for that field:

tokens: Tokens,

// ...

	pub fn init(allocator: Allocator, source: []const u8) Lexer {
		return .{
			.source = source,
			.tokens = Tokens.init(allocator),
		};
	}
1 Like

Fantastic. Thanks a million.

I was running into other problems when running tests, but didn’t realize that it was because I was leaking memory. I fixed that now so it’s all good.

Thanks again.

-kow

It would great if Zig had performed escape analysis at comptime to prevent pointers to stack-allocated memory from getting returned from function calls. This would eliminate a whole class of memory bugs.
If not the language itself but may be an escape linter.

1 Like

There is an open issue.

2 Likes