Cannot understand what is wrong with my init function

Hi,

My test program has a behavior that I can not explain and I feel like I am missing something really simple:

const std = @import ("std");

const Color = enum (u8) { Red = 1, Green, };
const Fruit = enum (u8) { Banana = 1, Apple, };

const ColoredFruit = struct {
  color: Color = undefined,
  fruit: Fruit = undefined,

  fn init (fruit: Fruit, color: Color) @This () {
    return .{ .color = color, .fruit = fruit, };
  }
};

fn fill () [] const ColoredFruit {
  //return &.{.{ .fruit = .Banana, .color = .Green },.{ .fruit = .Apple, .color = .Red }};
  return &.{ ColoredFruit.init (.Banana, .Green), ColoredFruit.init (.Apple, .Red) };
}

const Bucket = struct {
  slice: [] const ColoredFruit = undefined,

  fn init () !@This () {
    const bucket = .{ .slice = fill () };
    for (0..bucket.slice.len) |i| std.debug.print ("bucket.slice[{}]: {}\n", .{i,bucket.slice[i]});
    return bucket;
  }
};

test "bucket" {
  _ = try Bucket.init ();
}

When I am running my zig test command line, I get the following output (because it is not easy to read I only kept the 2 first lines):

$ zig test bucket.zig
Test [1/1] test.ok... bucket.slice[0]: bucket.ColoredFruit{ .color = bucket.Color.Green, .fruit = bucket.Fruit.Banana }
bucket.slice[1]: bucket.ColoredFruit{ .color = bucket.Color.thread 54742 panic: invalid enum value

However when I switch the commented and uncommented lines into the fill () function, here the result:

$ zig test bucket.zig
Test [1/1] test.ok... bucket.slice[0]: bucket.ColoredFruit{ .color = bucket.Color.Green, .fruit = bucket.Fruit.Banana }
bucket.slice[1]: bucket.ColoredFruit{ .color = bucket.Color.Red, .fruit = bucket.Fruit.Apple }
All 1 tests passed.

What is wrong with my ColoredFruit.init () function ?

Thank you.

In this case, the array you are taking a slice of is allocated on stack and gets deallocated once the function returns. Your print function then reads this now invalid memory.
Non-comptime functions are always called at runtime.

Here it doesn’t happen because all the values are compile time known, which gives the array static lifetime (is valid for the entire duration of the program).

2 Likes

Thank you for your answer and for taking the time to explain this @bnl1.

3 Likes