Hi! The following snippet produces an "attempt to access a nil address" error, but only with the devel version, and only when parseAtlas is executed at compile time (the offending line is marked with a comment; only parseAtlas seems directly relevant):
const file = """
sprites.png
size: 1024,1024
format: RGBA8888
filter: Linear,Linear
repeat: none
char/slide_down
rotate: false
xy: 730, 810
size: 204, 116
orig: 204, 116
offset: 0, 0
index: -1
"""
type
AtlasPage = object
width, height: int
path: string
CtsStream = object
data: string
pos: int
# ************
# Crappy string stream implementation, because Nim's doesn't work at compile time:
# Probably not interesting, but seems necessary to reproduce the bug.
# ************
proc atEnd(stream: CtsStream): bool =
stream.pos >= stream.data.len
proc readChar(stream: var CtsStream): char =
if stream.atEnd:
result = '\0'
else:
result = stream.data[stream.pos]
inc stream.pos
proc readLine(s: var CtsStream, line: var string): bool =
# This is pretty much copied from the standard library:
line.setLen(0)
while true:
var c = readChar(s)
if c == '\c':
c = readChar(s)
break
elif c == '\L': break
elif c == '\0':
if line.len > 0: break
else: return false
line.add(c)
result = true
proc peekLine(s: var CtsStream, line: var string): bool =
let oldPos = s.pos
result = s.readLine(line)
s.pos = oldPos
proc initCtsStream(data: string): CtsStream =
CtsStream(
pos: 0,
data: data
)
# ********************
# Interesting stuff happens here:
# ********************
proc parseAtlas(stream: var CtsStream) =
var pages: seq[AtlasPage] = @[]
while not stream.atEnd:
# Read a page:
pages.add(AtlasPage())
var page = addr pages[^1]
var line = ""
discard stream.readLine(line)
while peekLine(stream, line) and line != "":
echo page == nil
discard stream.readLine(line)
let u0 = 100 / page.width # <----------------------- Crash happens here! --------
static:
var stream = initCtsStream(file)
parseAtlas(stream)
echo "Done!"
I couldn't shorten it any further. Even replacing the inner loop inside parseAtlas with a for that has the same body and executes the same number of times makes the error disappear. Perhaps I'm doing something questionable with that page pointer?When I ran your snipped with "run" button in forum, it didn't crash.
Oh, only happened with devel version, I guess regression bug?
Hi StasB!
If it is important for you can try to investigate it youself. I find it is easy with Nim.
Build nim_temp using command (takes 6 seconds):
koch temp
Try building your code with nim_temp as usual:
nim_temp c your_nim_file
You should get a nice stacktrace and good intuition where the problem is. More details: https://github.com/nim-lang/Nim/wiki/Debugging-the-compiler
It is something related to line:
page = addr pages[^1]
The following works fine:
proc parseAtlas(stream: var CtsStream) =
var pages: seq[AtlasPage] = @[]
while not stream.atEnd:
# Read a page:
pages.add(AtlasPage())
var line = ""
discard stream.readLine(line)
while peekLine(stream, line) and line != "":
discard stream.readLine(line)
let u0 = 100 / pages[^1].width
I have followed my advice, and got a stacktrace of compiler crash:
nim.nim(121) nim
nim.nim(77) handleCmdLine
main.nim(173) mainCommand
main.nim(77) commandCompileToC
modules.nim(242) compileProject
modules.nim(182) compileModule
passes.nim(250) processModule
passes.nim(139) processTopLevelStmt
sem.nim(576) myProcess
sem.nim(544) semStmtAndGenerateGenerics
semstmts.nim(1911) semStmt
semexprs.nim(793) semExprNoType
semexprs.nim(2396) semExpr
semstmts.nim(1758) semStaticStmt
vm.nim(1659) evalStaticStmt
vm.nim(1649) evalConstExprAux
vm.nim(787) rawExecute
system.nim(2839) sysFatal
Error: unhandled exception: node is not accessible [FieldError]
So it likely that the problem is in vm.nim file. At the top of vm.nim there are two constants that should be helpful producing assembly like output: debugEchoCode, traceCode