Hi there, I’m a newbie here.
I have an issue for the following simple code, result for the State_1 is incorrect (the result is random values), whereas result for Stage_2 is correct.
Pls kindly help what is wrong with the following code, thanks.
// A slice manipulation program
package main
import "core:fmt"
State:: struct {
aa, bb, cc, dd: int
}
route:: proc(state: State) -> []State {
state_2: []State = {state} //Assigning state_2 with 'state' and converting to slice
fmt.println("State_2: ", state_2) //Correct, state_2 result is 1, 0, 0, 1
return state_2
}
main:: proc() {
initial: State = {1, 0, 0, 1} // Initializing the state
state_1 := route(initial) // Call the procedure
fmt.println("\nState_1: ", state_1) //This state_1 is giving a wrong result (not being 1, 0, 0,1)
}
Short answer: you are returning stack memory in route. The compiler wasn’t clever enough to catch this case, and as such, you need to make sure not do this.
From this, you should be able to tell it is using stack memory now, and thus you cannot return it from a procedure. This is because Odin has manual memory management.
Thanks a lot for sharing your insights.
With your suggestion, the syntax worked.
Furthermore, the procedure is also working by specifying [1] State or [dynamic]State in the ‘route’ header.
route:: proc(state: State) -> [1]State {
state_2: [1]State = {state} // Assigning state_2 with 'state' and converting it to slice
//
return state_2
}
or
route:: proc(state: State) -> [dynamic]State {
state_2: [dynamic]State = {state} // Assigning state_2 with 'state' and converting it to slice
//
return state_2
}
At a glance, this looks to me like it would have the same issue as your original snippet. I’m surprised it works. If I’m not mistaken, it’s considered a best practice to always construct a dynamic array only using the make procedure group (or the procedures make_dynamic_array, make_dynamic_array_len, and make_dynamic_array_len_cap), and I recommend you do that.
Regardless of that, I venture to guess say that returning a fixed-size array would be better in most cases.
That works because creating a [dynamic] with a compound literal will implicitly allocate using context.allocator and populate the data. This is one of the few (somewhat) implicit allocations in Odin, and so it is often avoided. There’s even a compiler flag to disallow this entirely (-no-dynamic-literals).
You may also consider using Small_Array from core:container/small_array if the number of return values might be variable (but you know what the maximum is). That is effectively just a fixed array and a number of values that should actually be used–like a [dynamic], but with the data stored inline (and thus, a fixed capacity).