# Segfaults on implementing an interface

**URL:** <https://ziggit.dev/t/segfaults-on-implementing-an-interface/3563>\
**Category:** Help\
**Tags:** language\
**Created:** [March 14, 2024, 8:27am UTC](https://ziggit.dev/t/segfaults-on-implementing-an-interface/3563 "2024-03-14T08:27:53Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![timfayz](https://ziggit.dev/user_avatar/ziggit.dev/timfayz/32/1827_2.png) [@timfayz](https://ziggit.dev/u/timfayz)\
**Post date:** [March 14, 2024, 8:27am UTC](https://ziggit.dev/t/segfaults-on-implementing-an-interface/3563/1 "2024-03-14T08:27:53Z")

</div>

Hi everyone! I’m trying to implement a simple interface (for learning purposes) named `Shape1` which will hopefully allow me to iterate over different shapes generically and execute shapes’ `area()` methods accordingly:

```js
const Circle = struct {
    radius: f32,
    fn area(self: *anyopaque) f32 {
        const s: *const Circle = @ptrCast(@alignCast(self));
        return std.math.pi * s.radius * s.radius;
    }
};

const Square = struct {
    side: f32,
    fn area(self: *anyopaque) f32 {
        const s: *const Square = @ptrCast(@alignCast(self));
        return s.side * s.side;
    }
};

const Shape1 = struct {
    ptr: *anyopaque,
    vtab: *const VTab,

    const VTab = struct {
        areaFn: *const fn (ptr: *anyopaque) f32,
    };

    fn area(self: *Shape1) f32 {
        return self.vtab.areaFn(self.ptr);
    }

    fn init(ptr: *anyopaque, f: *const fn (ptr: *anyopaque) f32) Shape1 {
        return .{
            .ptr = ptr,
            .vtab = &VTab{ .areaFn = f },
        };
    }
};

pub fn main() !void {
    var sq = Square{ .side = 2 };
    var cr = Circle{ .radius = 2 };
    var shapes = [_]Shape1{
        Shape1.init(&sq, Square.area),
        Shape1.init(&cr, Circle.area),
    };
    for (&shapes) |*shape| {
        std.log.debug("{d}", .{shape.area()});
    }
}

```

First, I was trying to use `ptr: *const anyopaque` and it succeeded. Then, I switched to non-const pointers and now code segfaults. Stepping in the debugger showed it happens as soon as I access `shape` in the loop. Tbh, I’m not sure why. All the things reside on the stack and the accessing them shouldn’t be a problem.

I tried to get rid of `&Vtable {...}` in `init` by simply inlining `areaFn` into `Shape1` itself. And it worked! Segfault disappeared. However, in the repo explaining different approaches to implementing interface ([here](https://github.com/yglcode/zig_interfaces)), the author uses `&VTab{}` in the same `init()` successfully, without using any allocator.

What do I do wrong?

---

<div class="post-metadata">

**Author:** ![AndrewCodeDev](https://ziggit.dev/letter_avatar_proxy/v4/letter/a/278dde/32.png) [@AndrewCodeDev](https://ziggit.dev/u/AndrewCodeDev)\
**Post date:** [March 14, 2024, 8:33am UTC](https://ziggit.dev/t/segfaults-on-implementing-an-interface/3563/2 "2024-03-14T08:33:20Z")

</div>

You’re sharing one vtable between all the individual types. This won’t work because that single vtable is getting its functions switched out.

You need to have a method that returns a shape on each type so they can each have their own vtable.

---

<div class="post-metadata">

**Author:** ![dimdin](https://ziggit.dev/user_avatar/ziggit.dev/dimdin/32/1457_2.png) [@dimdin](https://ziggit.dev/u/dimdin)\
**Post date:** [March 14, 2024, 8:34am UTC](https://ziggit.dev/t/segfaults-on-implementing-an-interface/3563/3 "2024-03-14T08:34:08Z")

</div>

In `init` `VTab{ .areaFn = f }` is allocated in stack, its lifetime ends when exiting init but you get a pointer to that memory that its contents are replaced.

One way to solve this is to move the construction of vtable in each shape where `f` is constant and the `VTab` allocation can be static.

---

<div class="post-metadata">

**Author:** ![timfayz](https://ziggit.dev/user_avatar/ziggit.dev/timfayz/32/1827_2.png) [@timfayz](https://ziggit.dev/u/timfayz)\
**Post date:** [March 14, 2024, 8:35am UTC](https://ziggit.dev/t/segfaults-on-implementing-an-interface/3563/4 "2024-03-14T08:35:18Z")

</div>

A concrete example maybe? I’m not sure I’m getting you both 🙂

---

<div class="post-metadata">

**Author:** ![timfayz](https://ziggit.dev/user_avatar/ziggit.dev/timfayz/32/1827_2.png) [@timfayz](https://ziggit.dev/u/timfayz)\
**Post date:** [March 14, 2024, 8:36am UTC](https://ziggit.dev/t/segfaults-on-implementing-an-interface/3563/5 "2024-03-14T08:36:27Z")

</div>

> In `init` `VTab{ .areaFn = f }` is allocated in stack, its lifetime ends when exiting init but you get a pointer to that memory that its contents are replaced.

Then, the original code [here](https://github.com/yglcode/zig_interfaces?tab=readme-ov-file#interface-2-1st-implementation-of-vtable-and-dynamic-disptaching) is wrong?

---

<div class="post-metadata">

**Author:** ![AndrewCodeDev](https://ziggit.dev/letter_avatar_proxy/v4/letter/a/278dde/32.png) [@AndrewCodeDev](https://ziggit.dev/u/AndrewCodeDev)\
**Post date:** [March 14, 2024, 8:36am UTC](https://ziggit.dev/t/segfaults-on-implementing-an-interface/3563/6 "2024-03-14T08:36:33Z")

</div>

Sure, I’ll let @dimdin speak to the stack lifetime issue, I’ll draft up a godbolt example here to show you what I mean… uno momento…

---

<div class="post-metadata">

**Author:** ![dimdin](https://ziggit.dev/user_avatar/ziggit.dev/dimdin/32/1457_2.png) [@dimdin](https://ziggit.dev/u/dimdin)\
**Post date:** [March 14, 2024, 8:47am UTC](https://ziggit.dev/t/segfaults-on-implementing-an-interface/3563/7 "2024-03-14T08:47:57Z")

</div>

```zig
const std = @import("std");

const VTab = struct {
    areaFn: *const fn (ptr: *anyopaque) f32,
};

const Circle = struct {
    radius: f32,
    fn area(self: *anyopaque) f32 {
        const s: *const Circle = @ptrCast(@alignCast(self));
        return std.math.pi * s.radius * s.radius;
    }
    pub fn vtable() *const VTab {
        return &VTab{ .areaFn = Circle.area };
    }
};

const Square = struct {
    side: f32,
    fn area(self: *anyopaque) f32 {
        const s: *const Square = @ptrCast(@alignCast(self));
        return s.side * s.side;
    }
    pub fn vtable() *const VTab {
        return &VTab{ .areaFn = Square.area };
    }
};

const Shape1 = struct {
    ptr: *anyopaque,
    vtab: *const VTab,

    fn area(self: *Shape1) f32 {
        return self.vtab.areaFn(self.ptr);
    }

    fn init(ptr: *anyopaque, vtab: *const VTab) Shape1 {
        return .{
            .ptr = ptr,
            .vtab = vtab,
        };
    }
};

pub fn main() !void {
    var sq = Square{ .side = 2 };
    var cr = Circle{ .radius = 2 };
    var shapes = [_]Shape1{
        Shape1.init(&sq, Square.vtable()),
        Shape1.init(&cr, Circle.vtable()),
    };
    for (&shapes) |*shape| {
        std.log.debug("{d}", .{shape.area()});
    }
}

```

EDIT:  
Why this works?

```zig
pub fn vtable() *const VTab {
        return &VTab{ .areaFn = Square.area };
}

```

Since the members of VTab are all constant, allocation is static. We get a VTab pointer to the static space that does not change.

Why this does not work?

```zig
fn init(ptr: *anyopaque, f: *const fn (ptr: *anyopaque) f32) Shape1 {
    return .{
        .ptr = ptr,
        .vtab = &VTab{ .areaFn = f },
    };
}

```

Here VTab is not constant, f comes in runtime. Since VTab is allocated locally, it is allocated in stack.  
When init finishes the stack space is reused by other functions and its value becomes corrupted.

Discussion: [Feel confused with lifetime of anonymous struct](https://ziggit.dev/t/feel-confused-with-lifetime-of-anonymous-struct/2977)

---

<div class="post-metadata">

**Author:** ![timfayz](https://ziggit.dev/user_avatar/ziggit.dev/timfayz/32/1827_2.png) [@timfayz](https://ziggit.dev/u/timfayz)\
**Post date:** [March 14, 2024, 9:00am UTC](https://ziggit.dev/t/segfaults-on-implementing-an-interface/3563/8 "2024-03-14T09:00:21Z")

</div>

> [@dimdin](#):
>
> In `init` `VTab{ .areaFn = f }` is allocated in stack, its lifetime ends when exiting init but you get a pointer to that memory that its contents are replaced.
> 
> One way to solve this is to move the construction of vtable in each shape where `f` is constant and the `VTab` allocation can be static.

I don’t know… It looks ugly tbh, like an ad-hoc or something and I’m still not sure why this works and the other one didn’t. Why returning `return &VTab{ .areaFn = Square.area }` in the shape structs itself magically makes VTab static? Also, I would appreaciate to hear some comments on the original code I’m learning from ([GitHub - yglcode/zig\_interfaces: Interfaces in ziglang](https://github.com/yglcode/zig_interfaces?tab=readme-ov-file#interface-2-1st-implementation-of-vtable-and-dynamic-disptaching)) because it seems to work fine:

```zig
const std = @import("std");

const Point = struct {
    x: i32 = 0,
    y: i32 = 0,
    pub fn move(self: *Point, dx: i32, dy: i32) void {
        self.x += dx;
        self.y += dy;
    }
    pub fn draw(self: *Point) void {
        std.debug.print("point@<{d},{d}>\n", .{ self.x, self.y });
    }
};

const Shape2 = struct {
    ptr: *anyopaque,
    vtab: *const VTab,
    const VTab = struct {
        draw: *const fn (ptr: *anyopaque) void,
        move: *const fn (ptr: *anyopaque, dx: i32, dy: i32) void,
    };

    pub fn draw(self: Shape2) void {
        self.vtab.draw(self.ptr);
    }
    pub fn move(self: Shape2, dx: i32, dy: i32) void {
        self.vtab.move(self.ptr, dx, dy);
    }

    pub fn init(obj: anytype) Shape2 {
        const Ptr = @TypeOf(obj);
        const impl = struct {
            fn draw(ptr: *anyopaque) void {
                const self: Ptr = @ptrCast(@alignCast(ptr));
                self.draw();
            }
            fn move(ptr: *anyopaque, dx: i32, dy: i32) void {
                const self: Ptr = @ptrCast(@alignCast(ptr));
                self.move(dx, dy);
            }
        };
        return .{
            .ptr = obj,
            .vtab = &.{
                .draw = impl.draw,
                .move = impl.move,
            },
        };
    }
};

pub fn main() !void {
    var p1 = Point{ .x = 1, .y = 2 };
    var p2 = Point{ .x = 3, .y = 4 };
    var shapes = [_]Shape2{
        Shape2.init(&p1),
        Shape2.init(&p2),
    };
    for (&shapes) |*shape| {
        shape.draw();
    }
}

```

UPDATE:

Aha! I see why it works in the original code above. `impl` struct is constant and all its members are comptime known so it seems it automatically become static, right?

---

<div class="post-metadata">

**Author:** ![timfayz](https://ziggit.dev/user_avatar/ziggit.dev/timfayz/32/1827_2.png) [@timfayz](https://ziggit.dev/u/timfayz)\
**Post date:** [March 14, 2024, 9:02am UTC](https://ziggit.dev/t/segfaults-on-implementing-an-interface/3563/9 "2024-03-14T09:02:02Z")

</div>

@dimdin Thanks for the EDIT. It indeed explains the lifetime of VTab thing.

---

<div class="post-metadata">

**Author:** ![AndrewCodeDev](https://ziggit.dev/letter_avatar_proxy/v4/letter/a/278dde/32.png) [@AndrewCodeDev](https://ziggit.dev/u/AndrewCodeDev)\
**Post date:** [March 14, 2024, 9:09am UTC](https://ziggit.dev/t/segfaults-on-implementing-an-interface/3563/10 "2024-03-14T09:09:44Z")

</div>

My take is a little different than @dimdin’s, but I think you’ll see the similarity because we’re saying something similar. Here’s an example that I drafted - basically, same idea, just using different names. Each type has a function that returns an Interface with a vtable.

```zig
const VTable = struct {
    vcall: *const fn(*const anyopaque) i32,
};

const Interface = struct {
    ptr: *const anyopaque,
    vtable: *const VTable,
    pub fn call(self: Interface) i32 {
        return self.vtable.vcall(self.ptr);
    }
};

const Foo = struct {
    x: i32,

    pub fn call(ctx: *const anyopaque) i32 {
        const self: *const Foo = @ptrCast(@alignCast(ctx));
        return self.x;
    }

    pub fn interface(self: *const Foo) Interface {
        return Interface {
            .ptr = self,
            .vtable = &.{ .vcall = call },
        };
    }
};

const Bar = struct {
    x: i32,
    y: i32,
    pub fn call(ctx: *const anyopaque) i32 {
        const self: *const Bar = @ptrCast(@alignCast(ctx));
        return self.x + self.y;
    }

    pub fn interface(self: *const Bar) Interface {
        return Interface {
            .ptr = self,
            .vtable = &.{ .vcall = call },
        };
    }
};

fn doCall(a: Interface, b: Interface) i32 {
    return a.call() * b.call();
}

export fn something() i32 {
    const foo = Foo{ .x = 42 };
    const bar = Bar{ .x = 43, .y = 7 };

    const a = foo.interface();
    const b = bar.interface();

    const out = @call(.never_inline, doCall, .{ a, b });
    return out;    
}

```

I’ve done `@call(.never_inline` because I don’t want the compiler to see through this trivial example.

Anyway, if we look at the assembly, we can see this…

```zig
example.Foo.interface__anon_1002:
        .quad example.Foo.call

example.Bar.interface__anon_1004:
        .quad example.Bar.call

```

These anonymous values are holding our function pointers - you can see we got two of them, one for each interface function. These will get referenced when I make an interface:

```zig
example.Foo.interface:
        push rbp
        mov rbp, rsp
        push rax
        mov rax, rdi
        mov qword ptr [rbp - 8], rsi
        mov qword ptr [rdi], rsi
        movabs rcx, offset example.Foo.interface__anon_1002
        mov qword ptr [rdi + 8], rcx
        add rsp, 8
        pop rbp
        ret

```

So you can see that we’re loading in a different location somewhere else in the code - that’s where the vtables live. If you add more functions to it, you’ll see them stack up there.

Now why do we have two? We have two because each `interface` function has its own `vtable` unique to it because they are two separate functions. So we’re getting two separate vtables because we have made two different _literal_ vtables (in the same sense as a string literal) in two separate function implementations.

In other words, you get a vtable for `Foo`’s and a vtable for `Bar`’s.

---

<div class="post-metadata">

**Author:** ![timfayz](https://ziggit.dev/user_avatar/ziggit.dev/timfayz/32/1827_2.png) [@timfayz](https://ziggit.dev/u/timfayz)\
**Post date:** [March 14, 2024, 10:34am UTC](https://ziggit.dev/t/segfaults-on-implementing-an-interface/3563/11 "2024-03-14T10:34:54Z")

</div>

I had to take a break. I was upset not being able to understand it all. Such a waste! Anyway, thank you for the effort and the code above. At least your approach with `interface()` methods in each of the struct looks familiar with what I saw in the std lib.

The rest, including assembly, is simply beyond my brain capacity 🥲 . However, I’ll try my best and explain what I supposedly understood:

These:

```zig
example.Foo.interface__anon_1002:
        .quad example.Foo.call

example.Bar.interface__anon_1004:
        .quad example.Bar.call

```

Possibly refer to these lines:

```zig
const Foo|Bar = struct {
    pub fn interface(self: *const Foo|Bar) Interface {
        return Interface {
           ...
           .vtable = &.{ .vcall = call }, 
                     ^ (Foo|Bar).interface__anon_* static structures

```

Which should show that…ehm…zig compiler prepared a couple of `VTable` instances as static data in the scope of each Foo/Bar struct.

Then, the implementation of `example.Foo|Bar.interface` in assembly, as I said, I simply cannot understand. I think I need a separate book for it (is there any not 800-page-long-you-will-never-read?) I assume that this asm block (with pro and epilogs trimmed) fills/initialize the `Interface` and store it into the addresses the `rbp` and `rdi` are pointing to. But I think you just wanted to point out that during this initialization, we can see zig uses that static data (`example.(Foo|Bar).call`s) mentioned above.

If my assumptions were true, then the explanation on why do we get two separate vtable instances that are static:

> Now why do we have two? We have two because each `interface` function has its own `vtable` unique to it because they are two separate functions. So we’re getting two separate vtables because we have made two different _literal_ vtables (in the same sense as a string literal) in two separate function implementations.

Starts to makes sense and taking `&` address of “literal values”/structs in the implementation is safe as soon as zig knows the … [and here is the key to predict when zig indeed makes things static so that we can rely on their addresses]

---

<div class="post-metadata">

**Author:** ![timfayz](https://ziggit.dev/user_avatar/ziggit.dev/timfayz/32/1827_2.png) [@timfayz](https://ziggit.dev/u/timfayz)\
**Post date:** [March 14, 2024, 10:42am UTC](https://ziggit.dev/t/segfaults-on-implementing-an-interface/3563/12 "2024-03-14T10:42:32Z")

</div>

Since no one wanted 🙂 to comment why the original implementation worked relative to mine, I would ask directly:

```zig
pub fn init(obj: anytype) Shape2 {
    const Ptr = @TypeOf(obj);
    const impl = struct {
        fn draw(ptr: *anyopaque) void {
            const self: Ptr = @ptrCast(@alignCast(ptr));
            self.draw();
        }
        fn move(ptr: *anyopaque, dx: i32, dy: i32) void {
            const self: Ptr = @ptrCast(@alignCast(ptr));
            self.move(dx, dy);
        }
    };
    return .{
        .ptr = obj,
        .vtab = &.{ // THIS
            .draw = impl.draw,
            .move = impl.move,
        },
    };
}

```

Can I assume that the reason why the code above works is because in the place of THIS zig creates static vtable instances for every `obj` passed in into `init()`? (again, because `anytype` means zig would spawn a separate function for every type passed in)

---

<div class="post-metadata">

**Author:** ![AndrewCodeDev](https://ziggit.dev/letter_avatar_proxy/v4/letter/a/278dde/32.png) [@AndrewCodeDev](https://ziggit.dev/u/AndrewCodeDev)\
**Post date:** [March 14, 2024, 10:50am UTC](https://ziggit.dev/t/segfaults-on-implementing-an-interface/3563/13 "2024-03-14T10:50:37Z")

</div>

You basically have it. Let me make a comparison here to string literals and I think it will tie it up nicely.

Follow this example - we have a function called `foo` and `foo` just takes a string, gets it’s length, and the subtracts something from it (again, I’m just using `.never_inline` so the compiler doesn’t see right through what we’re trying to do):

```zig
fn count(x: []const u8) usize {
    return x.len;
}

export fn foo(x: usize) usize {
    const string: []const u8 = "hello";
    const len = @call(.never_inline, count, .{ string });
    return len - x;
}

```

Okay, so where does that string live? The thing is, it’s a _literal_ string. It gets lifted out of the function and put somewhere else… that looks like this:

```zig
__anon_1460:
        .asciz "hello"

```

So when we go to `__anon_1460` we find our string. It doesn’t live in the bounds of `foo`.

Now, where is our vtable literal? Here:

```zig
&.{ .vcall = call }

```

It’s just a value - it doesn’t have a name, and yet we’re taking an address to it? How is that possible and not invalid? Well, it’s because Zig treats this like the string literal and it’s been lifted into “static” data.

EDIT: It’s also important that the instantiation can be treated like a constant. If you can parameterize it on only runtime known data, you’ll get the OP’s original problem.

What’s important to understand here is each function has it’s own _unique_ vtable. This happens twice. Once for `foo` and once for `bar`. Hence, we have two vtables that live in a memory location that any instance of `Foo` or `Bar` can call:

```zig
const x: Foo...
const y: Foo...
// both get a pointer to the same vtable
const a = x.interface();
const b = y.interface();
``
```

---

<div class="post-metadata">

**Author:** ![timfayz](https://ziggit.dev/user_avatar/ziggit.dev/timfayz/32/1827_2.png) [@timfayz](https://ziggit.dev/u/timfayz)\
**Post date:** [March 14, 2024, 10:55am UTC](https://ziggit.dev/t/segfaults-on-implementing-an-interface/3563/14 "2024-03-14T10:55:37Z")

</div>

> [@AndrewCodeDev](#):
>
> (again, I’m just using `.never_inline` so the compiler doesn’t see right through what we’re trying to do)

What happens if zig will see it through? Optimize to the point where the call is unnecessary because we already know the length of “hello” and we can replace it with literal value inplace?

---

<div class="post-metadata">

**Author:** ![timfayz](https://ziggit.dev/user_avatar/ziggit.dev/timfayz/32/1827_2.png) [@timfayz](https://ziggit.dev/u/timfayz)\
**Post date:** [March 14, 2024, 10:56am UTC](https://ziggit.dev/t/segfaults-on-implementing-an-interface/3563/15 "2024-03-14T10:56:58Z")

</div>

> [@AndrewCodeDev](#):
>
> ```zig
> &.{ .vcall = call }
> 
> ```
> 
> It’s just a value - it doesn’t have a name, and yet we’re taking an address to it?

Will something change if we put the name? I thought the whole point was the _analysis_ of the content/values that forms this struct.

---

<div class="post-metadata">

**Author:** ![AndrewCodeDev](https://ziggit.dev/letter_avatar_proxy/v4/letter/a/278dde/32.png) [@AndrewCodeDev](https://ziggit.dev/u/AndrewCodeDev)\
**Post date:** [March 14, 2024, 10:58am UTC](https://ziggit.dev/t/segfaults-on-implementing-an-interface/3563/16 "2024-03-14T10:58:35Z")

</div>

Funny enough, it didn’t make a difference in this case - it’s just a habit of mine to stop the compiler from being smarter than the example I’m trying to make. I had to stay in debug mode.

Here’s all the assembly we get. I compile on release fast to remove debug symbols to find things more easily…

```zig
foo:
        mov eax, 5
        sub rax, rdi
        ret

```

The string doesn’t even exist in the code anymore.

---

<div class="post-metadata">

**Author:** ![AndrewCodeDev](https://ziggit.dev/letter_avatar_proxy/v4/letter/a/278dde/32.png) [@AndrewCodeDev](https://ziggit.dev/u/AndrewCodeDev)\
**Post date:** [March 14, 2024, 11:00am UTC](https://ziggit.dev/t/segfaults-on-implementing-an-interface/3563/17 "2024-03-14T11:00:28Z")

</div>

EDIT: Again, it’s also important that the instantiation can be treated like a constant. If you can parameterize it on only runtime known data, you’ll get the OP’s original problem.

It’s the fact that we’re taking a pointer to it and it can be treated like a constant - how can you take a pointer to it if it doesn’t exist somewhere? Since it has to exist somewhere, it’s gets lifted out and given an anonymous name.

Think of it this way - what’s a slice? It’s a pointer and a length. It’s pointing to _something_ and that happens to be a string. A slice isn’t the string, it’s a pointer to it.

If I have an array of `u8`, then there’s no need to lift it anywhere. That memory is right where we’re at.

Same as this - `const vtable = .{ .call = foo }`. We’ve declared that we are going to keep the memory local and call it vtable.

This however `const vtable: *const Vtable = &{ .call = foo }` is not a vtable, it’s a pointer to one. So where does the vtable itself live?

---

<div class="post-metadata">

**Author:** ![timfayz](https://ziggit.dev/user_avatar/ziggit.dev/timfayz/32/1827_2.png) [@timfayz](https://ziggit.dev/u/timfayz)\
**Post date:** [March 14, 2024, 11:12am UTC](https://ziggit.dev/t/segfaults-on-implementing-an-interface/3563/18 "2024-03-14T11:12:00Z")

</div>

I think I’m missing the main point in your explanation. It feels like it is not about taking an address of something that may not exist (and zig being so smart to automatically lift it up to somewhere else) but the point is _when_ zig can lift up. My conclusion is that the compiler can make thing static (ie. we can refer to it anywhere in the code) as soon as it is not _runtime_. My current list is:

- String literals
- Number literals
- Comptime known structs (otherwise, if for example 1 out of 10 fields of a struct happens to be runtime, then the whole struct cannot become static).
- Function declarations
- Globals?

---

<div class="post-metadata">

**Author:** ![AndrewCodeDev](https://ziggit.dev/letter_avatar_proxy/v4/letter/a/278dde/32.png) [@AndrewCodeDev](https://ziggit.dev/u/AndrewCodeDev)\
**Post date:** [March 14, 2024, 11:24am UTC](https://ziggit.dev/t/segfaults-on-implementing-an-interface/3563/19 "2024-03-14T11:24:52Z")

</div>

So let’s go back to your original code for a second and look at a bit more assembly (sorry to keep doing this to you, but it’s worth it).

Let’s just focus on that `init` function.

```zig
    fn init(ptr: *anyopaque, f: *const fn (ptr: *anyopaque) f32) Shape1 {
        return .{
            .ptr = ptr,
            .vtab = &VTab{ .areaFn = f },
        };
    }

```

Here comes the assembly…

```zig
example.Shape1.init:
        push rbp
        mov rbp, rsp
        sub rsp, 32
        mov rax, rdi
        mov qword ptr [rbp - 32], rsi
        mov qword ptr [rbp - 24], rdx
        mov qword ptr [rdi], rsi
        mov qword ptr [rbp - 16], rdx
        mov rcx, qword ptr [rbp - 16]
        mov qword ptr [rbp - 8], rcx
        lea rcx, [rbp - 8]
        mov qword ptr [rdi + 8], rcx
        add rsp, 32
        pop rbp
        ret

```

Notice something missing? Where’s the anonymous variable? Doesn’t exist. I’m going to take a stab here, but it looks like what has happened is that since it’s parameterizable by an unknown function at runtime, it can’t be treated like a constant. If it was, you wouldn’t be able to assign a new function to it every time you called `init`. So it gets created on the stack and dies when you leave.

That’s what @dimdin was saying with:

> [@dimdin](#):
>
> In `init` `VTab{ .areaFn = f }` is allocated in stack, its lifetime ends when exiting init but you get a pointer to that memory that its contents are replaced.

The difference here is that in the implementations where you take a parameter and assign it to that vtable, it can’t be constant and can’t be lifted out of the function.

The reason this works:

```zig
    pub fn init(obj: anytype) Shape2 {

```

Is because for every object type you pass to this function, you get a unique function to that type. It gets deduced and stamped out by the compiler. Then down here:

```zig
        return .{
            .ptr = obj,
            .vtab = &.{
                .draw = impl.draw,
                .move = impl.move,
            },

```

You only ever get one possible function for each `impl` that you’ve created. It’s always the same for any `obj` you pass in because you get unique types and only one function implementation provided per type. Because of that, the compiler knows that it’s always going to be the same, so it just makes one and makes it constant.

I’m speculating about how the compiler is thinking here, but effectively the result is the same. So I’ll append to my statement earlier…

It’s not just that it’s a pointer to a literal, it’s also that it can be treated like a constant.

---

<div class="post-metadata">

**Author:** ![timfayz](https://ziggit.dev/user_avatar/ziggit.dev/timfayz/32/1827_2.png) [@timfayz](https://ziggit.dev/u/timfayz)\
**Post date:** [March 14, 2024, 11:52am UTC](https://ziggit.dev/t/segfaults-on-implementing-an-interface/3563/20 "2024-03-14T11:52:05Z")

</div>

> The difference here is that in the implementations where you take a parameter and assign it to that vtable, it can’t be constant and can’t be lifted out of the function.

Yes, understood! Thank you. Honestly I realized it the first time you and @dimdin mentioned it. What I didn’t understand is the rules when compiler is be able to “lift” things out in _general_, so that I can predict the values “static-ability”.

I think these are some glimpses of these rules:

> It’s not just that it’s a pointer to a literal, it’s also that it can be treated like a constant.

> Because of that, the compiler knows that it’s always going to be the same, so it just makes one and makes it constant.

–––

> (sorry to keep doing this to you, but it’s worth it).

😃
