From d34345586ff276e25778a94fb268ceccde1daf26 Mon Sep 17 00:00:00 2001 From: Araq Date: Sun, 8 Jan 2012 20:18:24 +0100 Subject: [PATCH] unsuccessful phantom bug hunting --- compiler/ccgstmts.nim | 10 +++++++-- lib/system.nim | 50 ++++++++++++++++++++++--------------------- lib/system/alloc.nim | 17 ++++++++------- todo.txt | 2 +- 4 files changed, 44 insertions(+), 35 deletions(-) diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim index e00c4a3311..e4cc907f8f 100755 --- a/compiler/ccgstmts.nim +++ b/compiler/ccgstmts.nim @@ -319,8 +319,14 @@ proc genStringCase(p: BProc, t: PNode) = # but we reserved a label, which we use later appcg(p, cpsStmts, "switch (#hashString($1) & $2) {$n", [rdLoc(a), toRope(bitMask)]) - for j in countup(0, high(branches)): - if branches[j] != nil: + for j in countup(0, high(branches)): + when false: + let interior = cast[int](interiorAllocatedPtr(addr(branches[0])))+ + 2*sizeof(pointer) + let brn = cast[int](cast[pointer](branches)) + if interior != brn: + echo "BUG! ", interior, "-", brn + if branches[j] != nil: appf(p.s[cpsStmts], "case $1: $n$2break;$n", [intLiteral(j), branches[j]]) appf(p.s[cpsStmts], "}$n") # else statement: diff --git a/lib/system.nim b/lib/system.nim index 274b8d94e0..ff0839b69e 100755 --- a/lib/system.nim +++ b/lib/system.nim @@ -808,9 +808,34 @@ when hasThreadSupport: else: {.pragma: rtlThreadVar.} +const + QuitSuccess* = 0 + ## is the value that should be passed to ``quit`` to indicate + ## success. + + QuitFailure* = 1 + ## is the value that should be passed to ``quit`` to indicate + ## failure. + +var program_result* {.exportc: "nim_$1".} = QuitSuccess + ## modify this varialbe to specify the exit code of the program + ## under normal circumstances. when the program is terminated + ## prematurelly using ``quit``, this value is ignored. + +proc quit*(errorcode: int = QuitSuccess) {. + magic: "Exit", importc: "exit", noDecl, noReturn.} + ## stops the program immediately; before stopping the program the + ## "quit procedures" are called in the opposite order they were added + ## with ``addQuitProc``. ``quit`` never returns and ignores any + ## exception that may have been raised by the quit procedures. + ## It does *not* call the garbage collector to free all the memory, + ## unless a quit procedure calls ``GC_collect``. + template sysAssert(cond, msg: expr) = # change this to activate system asserts - #if not cond: echo "[SYSASSERT] ", msg + #if not cond: + # echo "[SYSASSERT] ", msg + # quit 1 nil include "system/inclrtl" @@ -1530,29 +1555,6 @@ template newException*(exceptn, message: expr): expr = e.msg = message e -const - QuitSuccess* = 0 - ## is the value that should be passed to ``quit`` to indicate - ## success. - - QuitFailure* = 1 - ## is the value that should be passed to ``quit`` to indicate - ## failure. - -var program_result* {.exportc: "nim_$1".} = QuitSuccess - ## modify this varialbe to specify the exit code of the program - ## under normal circumstances. when the program is terminated - ## prematurelly using ``quit``, this value is ignored. - -proc quit*(errorcode: int = QuitSuccess) {. - magic: "Exit", importc: "exit", noDecl, noReturn.} - ## stops the program immediately; before stopping the program the - ## "quit procedures" are called in the opposite order they were added - ## with ``addQuitProc``. ``quit`` never returns and ignores any - ## exception that may have been raised by the quit procedures. - ## It does *not* call the garbage collector to free all the memory, - ## unless a quit procedure calls ``GC_collect``. - when not defined(EcmaScript) and not defined(NimrodVM): {.push stack_trace: off.} diff --git a/lib/system/alloc.nim b/lib/system/alloc.nim index c3478a7398..a7c504afca 100755 --- a/lib/system/alloc.nim +++ b/lib/system/alloc.nim @@ -479,14 +479,6 @@ proc getSmallChunk(a: var TMemRegion): PSmallChunk = # ----------------------------------------------------------------------------- -proc getCellSize(p: pointer): int {.inline.} = - var c = pageAddr(p) - result = c.size - -proc memSize(a: TMemRegion, p: pointer): int {.inline.} = - var c = pageAddr(p) - result = c.size - proc rawAlloc(a: var TMemRegion, requestedSize: int): pointer = sysAssert(roundup(65, 8) == 72, "rawAlloc 1") sysAssert requestedSize >= sizeof(TFreeCell), "rawAlloc 2" @@ -526,6 +518,8 @@ proc rawAlloc(a: var TMemRegion, requestedSize: int): pointer = sysAssert((cast[TAddress](result) and (MemAlign-1)) == 0, "rawAlloc 9") if c.free < size: ListRemove(a.freeSmallChunks[s], c) + sysAssert(((cast[TAddress](result) and PageMask) -% smallChunkOverhead()) %% + size == 0, "rawAlloc 21") else: size = roundup(requestedSize+bigChunkOverhead(), PageSize) # allocate a large block @@ -549,6 +543,8 @@ proc rawDealloc(a: var TMemRegion, p: pointer) = # `p` is within a small chunk: var c = cast[PSmallChunk](c) var s = c.size + sysAssert(((cast[TAddress](p) and PageMask) -% smallChunkOverhead()) %% + s == 0, "rawDealloc 3") var f = cast[ptr TFreeCell](p) #echo("setting to nil: ", $cast[TAddress](addr(f.zeroField))) sysAssert(f.zeroField != 0, "rawDealloc 1") @@ -570,6 +566,8 @@ proc rawDealloc(a: var TMemRegion, p: pointer) = ListRemove(a.freeSmallChunks[s div memAlign], c) c.size = SmallChunkSize freeBigChunk(a, cast[PBigChunk](c)) + sysAssert(((cast[TAddress](p) and PageMask) -% smallChunkOverhead()) %% + s == 0, "rawDealloc 2") else: # set to 0xff to check for usage after free bugs: when overwriteFree: c_memset(p, -1'i32, c.size -% bigChunkOverhead()) @@ -687,6 +685,9 @@ template InstantiateForRegion(allocator: expr) = proc interiorAllocatedPtr*(p: pointer): pointer = result = interiorAllocatedPtr(allocator, p) + proc isAllocatedPtr*(p: pointer): bool = + result = isAllocatedPtr(allocator, p) + proc deallocOsPages = deallocOsPages(allocator) proc alloc(size: int): pointer = diff --git a/todo.txt b/todo.txt index f80d2e5b10..97ee5ebd5e 100755 --- a/todo.txt +++ b/todo.txt @@ -1,7 +1,7 @@ version 0.8.14 ============== -- fix allocator bug +- fix memory corruption bug triggered by visual c++ in release mode - fix line info in assertions version 0.9.0