Release compilation produces 'Invalid memory access' error

My program works fine during non-release compilation, and I can make sure that the “Invalid memory access” error is not related to the binding API.

Even more strange is that I only fixed the bug by adding a line of puts "xxx" code.

Just add a call to the puts method. The link is here:

I wrote a piece of code that might be relevant to it. The report function for this code should return 0, but it returns 99, and the first puts call outputs a completely unrelated error value.

def report
  need_forward = false

  begin
    snapshot = 99 if need_forward
  rescue e : Exception
    return
  end

  puts snapshot # Wrong value, for example: 1068599224

  snapshot_id =
    if snapshot
      99
    else
      0
    end

  snapshot_id
end

puts report # => 99

Play link: https://play.crystal-lang.org/#/r/7bmf

The reason I found it is because I used return. But I still can’t understand this phenomenon.
Why is the type of snapshot not (Int32 | Nil) but Int32, why should it be filled with the wrong value when it is nil.

If I had to guess id vote it would have something to do with the fact its not being initialized. If you declare/initialize the variable to something else before the begin/rescue, it works as expected.

Kinda similar to Stricter inferrance option?

I moved snapshot out of the begin block and still used return in rescue.
This problem has been completely avoided.

def report
  need_forward = false

  snapshot =
    begin
      99 if need_forward
    rescue e : Exception
      return
    end

  puts snapshot.inspect # => nil
  puts typeof(snapshot) # => (Int32 | Nil)

  snapshot_id =
    if snapshot
      99
    else
      0
    end

  snapshot_id
end

puts report # => 0

However, the runtime is inconsistent after the release is compiled. There are also return and variable scopes. Much like some traps.

Thank you, reported here

2 Likes