Search code examples
odin-langodin

Why is this string blank after the procedure returns it (Odin)?


In the following small sample program, input is read from stdin. Printing the string value works inside read_input, but not in main. Surprisingly, the length (len) of the string does output in main, though the string output is blank.

main :: proc() {
    fmt.print("$ ")
    input := read_input()

    // This will output the proper length
    fmt.println("returned string length:", len(input))

    // This will be empty
    fmt.println("returned string: ", input)
}

read_input :: proc() -> string {
    buf: [256]byte
    num_bytes, err := os.read(os.stdin, buf[:])

    if err < 0 {
        return "Error reading from stdin"
    }

    str := string(buf[:num_bytes - 1])

    // this will output the proper number of bytes
    fmt.println("bytes read: ", num_bytes)

    // this will output the string entered, minus the newline
    fmt.println("read string: ", str)

    return str
}

Example run/output:

$ hello
bytes read:  6
read string:  hello
returned string length: 5
returned string: 

I've discovered that returning strings.clone(str) works but I'm not really understanding the problem above.


Solution

  • In Odin string is just a view over underlaying data buffer. In your case it points to buf which is local to read_input procedure. Once read_input returns its stack memory is gone, but returned string still points to it.

    strings.clone(str) works because it allocates memory for a string copy and return string which points into this memory. In this case you'll need to delete it in main to avoid memory leak.