Skip to content

Commit

Permalink
Fix memory leak in freeNode and splitNode.
Browse files Browse the repository at this point in the history
  • Loading branch information
keep94 committed Oct 4, 2016
1 parent 7364763 commit dd60200
Showing 1 changed file with 28 additions and 11 deletions.
39 changes: 28 additions & 11 deletions btree.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,9 @@ func (f *FreeList) newNode() (n *node) {
if index < 0 {
return new(node)
}
f.freelist, n = f.freelist[:index], f.freelist[index]
n = f.freelist[index]
f.freelist[index] = nil
f.freelist = f.freelist[:index]
return
}

Expand Down Expand Up @@ -153,6 +155,16 @@ func (s *items) pop() (out Item) {
return
}

// truncate truncates this instance at index so that it contains only the
// first index items. index must be less than or equal to length.
func (s *items) truncate(index int) {
l := len(*s)
for i := index; i < l; i++ {
(*s)[i] = nil
}
*s = (*s)[:index]
}

// find returns the index where the given item should be inserted into this
// list. 'found' is true if the item already exists in the list at the given
// index.
Expand Down Expand Up @@ -198,6 +210,16 @@ func (s *children) pop() (out *node) {
return
}

// truncate truncates this instance at index so that it contains only the
// first index children. index must be less than or equal to length.
func (s *children) truncate(index int) {
l := len(*s)
for i := index; i < l; i++ {
(*s)[i] = nil
}
*s = (*s)[:index]
}

// node is an internal node in a tree.
//
// It must at all times maintain the invariant that either
Expand All @@ -216,10 +238,10 @@ func (n *node) split(i int) (Item, *node) {
item := n.items[i]
next := n.t.newNode()
next.items = append(next.items, n.items[i+1:]...)
n.items = n.items[:i]
n.items.truncate(i)
if len(n.children) > 0 {
next.children = append(next.children, n.children[i+1:]...)
n.children = n.children[:i+1]
n.children.truncate(i + 1)
}
return item, next
}
Expand Down Expand Up @@ -532,14 +554,9 @@ func (t *BTree) newNode() (n *node) {
}

func (t *BTree) freeNode(n *node) {
for i := range n.items {
n.items[i] = nil // clear to allow GC
}
n.items = n.items[:0]
for i := range n.children {
n.children[i] = nil // clear to allow GC
}
n.children = n.children[:0]
// clear to allow GC
n.items.truncate(0)
n.children.truncate(0)
n.t = nil // clear to allow GC
t.freelist.freeNode(n)
}
Expand Down

0 comments on commit dd60200

Please sign in to comment.