Closed khchen closed 1 year ago
Cannot reproduce.
If you cannot minimize, please provide a different program that also fails for wNim, hopefully it crashes on my machine too then.
Can reproduce in Wine on latest devel :) Seems like it's not a cursorifier bug (crashes with cursorifier disabled)
After removing all macros and templates, the code looks like this. It works without --gc:arc, but crashes with --gc:arc.
import wNim/[wApp, wFrame, wButton, wResizer]
let app = App()
let frame = Frame()
let button = Button(frame)
proc layout() =
block:
var resizer {.inject, global.}: wResizer
if resizer == nil:
resizer = Resizer(frame)
resizer.addObject(button)
resizer.addConstraint(frame.mLeft == button.mLeft)
resizer.addConstraint(frame.mTop == button.mTop)
resizer.addConstraint(frame.mWidth == button.mWidth)
resizer.addConstraint(frame.mHeight == button.mHeight)
resizer.resolve()
resizer.rearrange()
frame.wEvent_Size do ():
layout()
layout()
frame.show()
frame.center()
app.mainLoop()
However, these code always works:
proc layout() =
# block:
var resizer {.inject, global.}: wResizer
proc layout() =
block:
var resizer {.inject.}: wResizer
In summary, the problem is related to block
and global
.
I hope someone can reproduce these results.
@khchen thanks for the simplification, it allowed me to repro it without any dependencies, can you please rename the issue (to something like "[ARC] Global variable declared in a block is destroyed too early") and add the repro to the first post ? :)
type
Resizer = ref object
data: string
proc layout() =
block:
var resizer {.global.}: Resizer
if resizer == nil:
resizer = Resizer(data: "hi")
discard resizer.data == "hi"
layout()
layout()
expandArc:
block :tmp:
var resizer
if resizer == nil:
`=sink`(resizer, Resizer(data: "hi"))
discard resizer.data == "hi"
`=destroy`(resizer)
The issue seems to be that the compiler doesn't recognize (or "forgets") about global pragma of a variable if it's in a block.
This bug is caused by this line: https://github.com/nim-lang/Nim/blob/devel/compiler/injectdestructors.nim#L530
Changing it to remove the weird parent restriction makes this example work, but makes another test fail.
IMO {.global.}
has extremely weird and underspecified semantics and should be deprecated; its easy to use them to create invalid C code simply by declaring a {.global.}
in a proc and making its value depend on one of the proc args. With --gc:arc
this might actually work, because they get created like normal variables on each call of the proc.
I think they are a minefield and I don't really see a usecase for them where a normal top-level global wouldn't do it (except for the part that they are initialized before those other globals, but maybe a {.earlyInit.}
pragma would be better served for that purpose).
Similar problem:
type
T = ref object
data: string
template foo(): T =
var a {.global.}: T
once:
a = T(data: "hi")
echo "init"
a
proc test() =
var a = foo()
echo a.data
test()
test()
Compile without --gc:arc
init hi
hi
Compile with --gc:arc
SIGSEGV: Illegal storage access. (Attempt to read from nil?)
Nim Compiler Version 1.4.0 [Windows: amd64]
Compiled at 2020-10-18
Copyright (c) 2006-2020 by Andreas Rumpf
Following code works well before the update: An optimizer for ARC (#14962). Compiling with --gc:arc.
Example
Current Output
Thanks to @Yardanico, the simplified code is