Runtime-mutating and passing around '[]const u8' character strings

Your get function is a very useful pattern for these use-cases. Short-lived temporary slices attached to arrays are idiomatic. But it could become problematic if a slice outlives its parent or points to the wrong side of the copy.

I may be missing some larger context here but why not simply store the bytes in an array list and upon update clear while retaining capacity? If the update is smaller than the original, no new allocs are performed. If it’s larger, you expand.

If on the other hand you want to store multiple strings, you could use a single array list of bytes and return start index and length for any newly added string to avoid use-after-move issues.

1 Like

finally found the time to try this, with some interesting results:

  • your code works as-is with zig 0.11
  • with zig 0.12-dev, I need to use fn get(self: *ToyStr) []const u8 { ...
    • that works as far as I can tell (debug, safe and fast mode tested)
  • with zig 0.12-dev, if I replace the pointer to self with self only, fn get(self: ToyStr) []u8 { ..., this does not work - why ?

I checked it with 0.12.0-dev.1769+bf5ab5451 (which I currently have on my machine, a bit outdated), works as with 0.11.0. It follows, something has been changed henceforward.

I don’t think it’s a good idea.
Yes, it stops working correctly, I got this output:

$ ./toy-str 
 (3 bytes)
bbbb (8 bytes)

Lengths are correct, but not the buffer content.
But I can not wise up quickly why it happens like this.

1 Like

Inside function everything is correct.
You put a copy on stack, made a slice of that copy,
returned that slice, but stack is already changed
and that slice became invalid.

Something like this.
So, pass an instance by reference, not by value.

1 Like

ah of course! I want to point to some data of that instance, not some copy…! why didn’t I spot this before, makes perfect sense ^^

will do so. Thanks for coming back to this!