From 5f83e869fa000598ab38866485dc8e58dd7d90d0 Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Wed, 15 Jun 2016 17:15:20 +0200 Subject: attempt to fix a critical memory leak in Nim's collections --- lib/pure/collections/sets.nim | 4 ++++ lib/pure/collections/tableimpl.nim | 8 ++++++++ 2 files changed, 12 insertions(+) (limited to 'lib/pure') diff --git a/lib/pure/collections/sets.nim b/lib/pure/collections/sets.nim index 20f73ded3..e2081e5bf 100644 --- a/lib/pure/collections/sets.nim +++ b/lib/pure/collections/sets.nim @@ -261,6 +261,8 @@ template doWhile(a: expr, b: stmt): stmt = b if not a: break +proc default[T](t: typedesc[T]): T {.inline.} = discard + proc excl*[A](s: var HashSet[A], key: A) = ## Excludes `key` from the set `s`. ## @@ -277,11 +279,13 @@ proc excl*[A](s: var HashSet[A], key: A) = var msk = high(s.data) if i >= 0: s.data[i].hcode = 0 + s.data[i].key = default(type(s.data[i].key)) dec(s.counter) while true: # KnuthV3 Algo6.4R adapted for i=i+1 instead of i=i-1 var j = i # The correctness of this depends on (h+1) in nextTry, var r = j # though may be adaptable to other simple sequences. s.data[i].hcode = 0 # mark current EMPTY + s.data[i].key = default(type(s.data[i].key)) doWhile ((i >= r and r > j) or (r > j and j > i) or (j > i and i >= r)): i = (i + 1) and msk # increment mod table size if isEmpty(s.data[i].hcode): # end of collision cluster; So all done diff --git a/lib/pure/collections/tableimpl.nim b/lib/pure/collections/tableimpl.nim index cc32fbedc..1bbf19ee9 100644 --- a/lib/pure/collections/tableimpl.nim +++ b/lib/pure/collections/tableimpl.nim @@ -110,18 +110,24 @@ template hasKeyOrPutImpl(enlarge) {.dirty, immediate.} = maybeRehashPutImpl(enlarge) else: result = true +proc default[T](t: typedesc[T]): T {.inline.} = discard + template delImpl() {.dirty, immediate.} = var hc: Hash var i = rawGet(t, key, hc) let msk = maxHash(t) if i >= 0: t.data[i].hcode = 0 + t.data[i].key = default(type(t.data[i].key)) + t.data[i].val = default(type(t.data[i].val)) dec(t.counter) block outer: while true: # KnuthV3 Algo6.4R adapted for i=i+1 instead of i=i-1 var j = i # The correctness of this depends on (h+1) in nextTry, var r = j # though may be adaptable to other simple sequences. t.data[i].hcode = 0 # mark current EMPTY + t.data[i].key = default(type(t.data[i].key)) + t.data[i].val = default(type(t.data[i].val)) while true: i = (i + 1) and msk # increment mod table size if isEmpty(t.data[i].hcode): # end of collision cluster; So all done @@ -137,4 +143,6 @@ template delImpl() {.dirty, immediate.} = template clearImpl() {.dirty, immediate.} = for i in 0 ..