Open
Description
The following snippet leads to a memory corruption as evident by the output (which changes during each run. It works fine with --newruntime
/--gc:arc|orc
or --gc:markAndSweep|boehm|go|none|regions
.
Example
import rationals
type
Probability = Rational[int]
Tile[n: static int] = object
a: array[n, Probability]
collapsed: bool
Map[w, h: static int, n: static int] = array[w, array[h, Tile[n]]]
TileId = int
Coord = tuple[x, y: int]
Rule[n: static int] = tuple[c: Coord, t: Tile[n]]
Discriminator[n: static int] = seq[Rule[n]]
Tileset[n: static int] = array[n, Discriminator[n]]
proc waveFunctionCollapse(result: var Map, tileset: Tileset) =
echo tileset
echo "XXX: Mem corruption: Rollout!"
for id in 0..<tileset.len:
for (c, t) in tileset[id]:
echo tileset[id] #XXX: Already corrupt here
proc waveFunctionCollapse[n: static int](tileset: Tileset[n], w, h: static int): Map[w, h, n] =
for x in 0..<w:
for y in 0..<h:
for i in 0..<n:
result[x][y].a[i] = 1//n
result.waveFunctionCollapse(tileset)
func prepareTileset(tileset: var Tileset) =
var additions: Tileset
for id, tile in tileset:
for rule in tile:
for i, p in rule.t.a:
additions[i].add(block:
var newRule: Rule[tileset.len]
newRule.c = (-rule.c.x, -rule.c.y)
for j in 0..<newRule.t.a.len: newRule.t.a[j] = 1//1 #Init to 1
newRule.t.a[id] = p / tileset.len
newRule)
for id, tile in additions:
for rule in tile:
tileset[id].add rule
#Add self discriminator
for id, tile in tileset.mpairs:
var newRule: Rule[tileset.len]
newRule.c = (0, 0)
for j in 0..<newRule.t.a.len: newRule.t.a[j] = 0//1 #Init to 0
newRule.t.a[id] = 1//1
tile.add newRule
func prepareTileset(tileset: Tileset): Tileset =
result = tileset
prepareTileset(result)
when isMainModule:
type Tiles = enum
Air, Land, Water, Wall
let unpreppedTileset: Tileset[4] = [
Air: @[],
Land: @[],
Water: @[],
Wall: @[
( (1, 1) , Tile[4](a: [Air: 0//1, Land: 0//1, Water: 0//1, Wall: 1//1]) ),
( (0, 1) , Tile[4](a: [Air: 0//1, Land: 0//1, Water: 0//1, Wall: 1//1]) ),
( (1, 0) , Tile[4](a: [Air: 0//1, Land: 0//1, Water: 0//1, Wall: 1//1]) ),
],
]
var preppedTileset = prepareTileset(unpreppedTileset)
echo "XXX: Not yet (visibly?) corrupt: ",preppedTileset
discard waveFunctionCollapse(preppedTileset, 12, 12)
Current Output
XXX: Not yet (visibly?) corrupt: [@[(c: (x: -1, y: -1), t: (a: [1/1, 1/1, 1/1, 0/1], collapsed: false)), (c: (x: 0, y: -1), t: (a: [1/1, 1/1, 1/1, 0/1], collapsed: false)), (c: (x: -1, y: 0), t: (a: [1/1, 1/1, 1/1, 0/1], collapsed: false)), (c: (x: 0, y: 0), t: (a: [1/1, 0/1, 0/1, 0/1], collapsed: false))], @[(c: (x: -1, y: -1), t: (a: [1/1, 1/1, 1/1, 0/1], collapsed: false)), (c: (x: 0, y: -1), t: (a: [1/1, 1/1, 1/1, 0/1], collapsed: false)), (c: (x: -1, y: 0), t: (a: [1/1, 1/1, 1/1, 0/1], collapsed: false)), (c: (x: 0, y: 0), t: (a: [0/1, 1/1, 0/1, 0/1], collapsed: false))], @[(c: (x: -1, y: -1), t: (a: [1/1, 1/1, 1/1, 0/1], collapsed: false)), (c: (x: 0, y: -1), t: (a: [1/1, 1/1, 1/1, 0/1], collapsed: false)), (c: (x: -1, y: 0), t: (a: [1/1, 1/1, 1/1, 0/1], collapsed: false)), (c: (x: 0, y: 0), t: (a: [0/1, 0/1, 1/1, 0/1], collapsed: false))], @[(c: (x: 1, y: 1), t: (a: [0/1, 0/1, 0/1, 1/1], collapsed: false)), (c: (x: 0, y: 1), t: (a: [0/1, 0/1, 0/1, 1/1], collapsed: false)), (c: (x: 1, y: 0), t: (a: [0/1, 0/1, 0/1, 1/1], collapsed: false)), (c: (x: -1, y: -1), t: (a: [1/1, 1/1, 1/1, 1/4], collapsed: false)), (c: (x: 0, y: -1), t: (a: [1/1, 1/1, 1/1, 1/4], collapsed: false)), (c: (x: -1, y: 0), t: (a: [1/1, 1/1, 1/1, 1/4], collapsed: false)), (c: (x: 0, y: 0), t: (a: [0/1, 0/1, 0/1, 1/1], collapsed: false))]]
[@[(c: (x: -1, y: -1), t: (a: [1/1, 1/1, 1/1, 0/1], collapsed: false)), (c: (x: 0, y: -1), t: (a: [1/1, 1/1, 1/1, 0/1], collapsed: false)), (c: (x: -1, y: 0), t: (a: [1/1, 1/1, 1/1, 0/1], collapsed: false)), (c: (x: 0, y: 0), t: (a: [1/1, 0/1, 0/1, 0/1], collapsed: false))], @[(c: (x: -1, y: -1), t: (a: [1/1, 1/1, 1/1, 0/1], collapsed: false)), (c: (x: 0, y: -1), t: (a: [1/1, 1/1, 1/1, 0/1], collapsed: false)), (c: (x: -1, y: 0), t: (a: [1/1, 1/1, 1/1, 0/1], collapsed: false)), (c: (x: 0, y: 0), t: (a: [0/1, 1/1, 0/1, 0/1], collapsed: false))], @[(c: (x: -1, y: -1), t: (a: [1/1, 1/1, 1/1, 0/1], collapsed: false)), (c: (x: 0, y: -1), t: (a: [1/1, 1/1, 1/1, 0/1], collapsed: false)), (c: (x: -1, y: 0), t: (a: [1/1, 1/1, 1/1, 0/1], collapsed: false)), (c: (x: 0, y: 0), t: (a: [0/1, 0/1, 1/1, 0/1], collapsed: false))], @[(c: (x: 1, y: 1), t: (a: [0/1, 0/1, 0/1, 1/1], collapsed: false)), (c: (x: 0, y: 1), t: (a: [0/1, 0/1, 0/1, 1/1], collapsed: false)), (c: (x: 1, y: 0), t: (a: [0/1, 0/1, 0/1, 1/1], collapsed: false)), (c: (x: -1, y: -1), t: (a: [1/1, 1/1, 1/1, 1/4], collapsed: false)), (c: (x: 0, y: -1), t: (a: [1/1, 1/1, 1/1, 1/4], collapsed: false)), (c: (x: -1, y: 0), t: (a: [1/1, 1/1, 1/1, 1/4], collapsed: false)), (c: (x: 0, y: 0), t: (a: [0/1, 0/1, 0/1, 1/1], collapsed: false))]]
XXX: Mem corruption: Rollout!
@[(c: (x: 140019704547016, y: 0), t: (a: [13/72, 2318281978072954920/176901077625, 0/0, 0/0], collapsed: false)), (c: (x: 0, y: -1), t: (a: [1/140019704547128, 0/12, 72/8728024663054776360, 691019834/0], collapsed: false)), (c: (x: 0, y: 0), t: (a: [1/1, 1/1, 140019704547240/0, 12/72], collapsed: true)), (c: (x: 691085370, y: 0), t: (a: [0/0, 0/1, 0/1, 0/140019704547352], collapsed: false))]
/home/clyybber/projects/tests/safememcorr.nim(73) safememcorr
/home/clyybber/projects/tests/safememcorr.nim(27) waveFunctionCollapse
/home/clyybber/projects/tests/safememcorr.nim(20) waveFunctionCollapse
/home/clyybber/builds/nim/lib/system/dollars.nim(134) $
/home/clyybber/builds/nim/lib/system/iterators.nim(189) collectionToString
/home/clyybber/builds/nim/lib/system/assertions.nim(27) failedAssertImpl
/home/clyybber/builds/nim/lib/system/assertions.nim(20) raiseAssert
/home/clyybber/builds/nim/lib/system/fatal.nim(39) sysFatal
Error: unhandled exception: /home/clyybber/builds/nim/lib/system/iterators.nim(189, 11) `len(a) == L` the length of the seq changed while iterating over it [AssertionError]
Possible Solution
Compiling with --newruntime
Additional Information
$ nim -v
Nim Compiler Version 1.0.0