Skip to content

Memory corruption #12273

Open
Open
@Clyybber

Description

@Clyybber

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions