summary refs log tree commit diff stats
path: root/tests/gc/gcleak4.nim
blob: 54e74ac7b9b8098542b6a4e9ae92d3fb90cb2fcd (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
discard """
  outputsub: "no leak: "
"""

when defined(GC_setMaxPause):
  GC_setMaxPause 2_000

type
  TExpr = object {.inheritable.} ## abstract base class for an expression
  PLiteral = ref TLiteral
  TLiteral = object of TExpr
    x: int
    op1: string
  TPlusExpr = object of TExpr
    a, b: ref TExpr
    op2: string
    
method eval(e: ref TExpr): int =
  # override this base method
  quit "to override!"

method eval(e: ref TLiteral): int = return e.x

method eval(e: ref TPlusExpr): int =
  # watch out: relies on dynamic binding
  return eval(e.a) + eval(e.b)

proc newLit(x: int): ref TLiteral =
  new(result)
  {.watchpoint: result.}
  result.x = x
  result.op1 = $getOccupiedMem()
  
proc newPlus(a, b: ref TExpr): ref TPlusExpr =
  new(result)
  {.watchpoint: result.}
  result.a = a
  result.b = b
  result.op2 = $getOccupiedMem()

const Limit = when compileOption("gc", "markAndSweep"): 5*1024*1024 else: 500_000

for i in 0..100_000:
  var s: array[0..11, ref TExpr]
  for j in 0..high(s):
    s[j] = newPlus(newPlus(newLit(j), newLit(2)), newLit(4))
    if eval(s[j]) != j+6:
      quit "error: wrong result"
  if getOccupiedMem() > Limit: quit("still a leak!")

echo "no leak: ", getOccupiedMem()