Opened 12 years ago
Closed 12 years ago
#10287 closed defect (fixed)
memleak in bitset_realloc()
Reported by:  Minh Van Nguyen  Owned by:  Robert Miller 

Priority:  major  Milestone:  sage4.6.1 
Component:  memleak  Keywords:  
Cc:  Merged in:  sage4.6.1.alpha3  
Authors:  Minh Van Nguyen  Reviewers:  Robert Miller 
Report Upstream:  N/A  Work issues:  
Branch:  Commit:  
Dependencies:  Stopgaps: 
Description (last modified by )
This is part of the larger project at #7656. See this thread for some background information.
The relevant module is
sage/misc/bitset.pxi
and the function concerned is bitset_realloc()
. A memleak occurs when we have a bitset of positive size (or capacity) and then reallocate the size to be zero. To pick up the memleak, I first loaded Sage 4.6.1.alpha1 under valgrind and quit Sage without doing any computation. The resulting memleak summary is:
==26274== LEAK SUMMARY: ==26274== definitely lost: 80 bytes in 3 blocks. ==26274== indirectly lost: 240 bytes in 10 blocks. ==26274== possibly lost: 562,324 bytes in 1,305 blocks. ==26274== still reachable: 60,547,159 bytes in 41,676 blocks. ==26274== suppressed: 0 bytes in 0 blocks. ==26274== Reachable blocks (those to which a pointer was found) are not shown. ==26274== To see them, rerun with: leakcheck=full showreachable=yes
I then applied the following patch to the Sage library, see test.patch:

module_list.py
# HG changeset patch # User Minh Van Nguyen <nguyenmi...@gmail.com> # Date 1289991585 28800 # Node ID 0554c5d2f725c4d29a6ca0176249b3febb235be2 # Parent 8c722bce2f917caab751122ef48b6057821142de imported patch test.patch diff git a/module_list.py b/module_list.py
a b 978 978 Extension('sage.misc.session', 979 979 sources = ['sage/misc/session.pyx']), 980 980 981 Extension('sage.misc.test', 982 sources = ['sage/misc/test.pyx']), 983 981 984 ################################ 982 985 ## 983 986 ## sage.modular 
new file sage/misc/test.pyx
diff git a/sage/misc/test.pyx b/sage/misc/test.pyx new file mode 100644
 + 1 include "../ext/stdsage.pxi" 2 include "bitset_pxd.pxi" 3 include "bitset.pxi" 4 5 def test(): 6 cdef bitset_t a 7 bitset_init(a, 10) 8 try: 9 bitset_realloc(a, 0) 10 except MemoryError: 11 pass 12 bitset_free(a)
I loaded Sage under valgrind again and performed the following computation:
sage: from sage.misc.test import test sage: test()
which resulted in the following memleak summary:
==16502== LEAK SUMMARY: ==16502== definitely lost: 88 bytes in 4 blocks. ==16502== indirectly lost: 240 bytes in 10 blocks. ==16502== possibly lost: 563,732 bytes in 1,308 blocks. ==16502== still reachable: 60,550,541 bytes in 41,691 blocks. ==16502== suppressed: 0 bytes in 0 blocks. ==16502== Reachable blocks (those to which a pointer was found) are not shown. ==16502== To see them, rerun with: leakcheck=full showreachable=yes
Notice that despite the function test()
explicitly freeing memory,
the report on "definitely lost" shows that we leaked an extra 8 bytes
(compare the 80 and 88 above in the first and second memleak
summaries, respectively). Finally, I applied the following patch to
the Sage library:

sage/misc/bitset.pxi
# HG changeset patch # User Minh Van Nguyen <nguyenmi...@gmail.com> # Date 1289992646 28800 # Node ID 9b5492b0ccc3a23626435f30433ebc52a673499f # Parent 0554c5d2f725c4d29a6ca0176249b3febb235be2 imported patch memleak.patch diff git a/sage/misc/bitset.pxi b/sage/misc/bitset.pxi
a b 52 52 cdef unsigned long size_old = bits.size 53 53 if size_old == size: return 0 54 54 bits.limbs = (size  1)/(8*sizeof(unsigned long)) + 1 55 bits.bits = <unsigned long*>sage_realloc(bits.bits, bits.limbs * sizeof(unsigned long)) 56 if bits.bits == NULL: 55 tmp = <unsigned long*>sage_realloc(bits.bits, bits.limbs * sizeof(unsigned long)) 56 if tmp != NULL: 57 bits.bits = tmp 58 else: 57 59 bits.limbs = limbs_old 58 60 raise MemoryError 59 61 bits.size = size
I loaded Sage under valgrind a third time and performed the following computation, same as above:
sage: from sage.misc.test import test sage: test()
The corresponding memleak summary is:
==22029== LEAK SUMMARY: ==22029== definitely lost: 80 bytes in 3 blocks. ==22029== indirectly lost: 240 bytes in 10 blocks. ==22029== possibly lost: 564,252 bytes in 1,309 blocks. ==22029== still reachable: 60,550,168 bytes in 41,696 blocks. ==22029== suppressed: 0 bytes in 0 blocks. ==22029== Reachable blocks (those to which a pointer was found) are not shown. ==22029== To see them, rerun with: leakcheck=full showreachable=yes
Notice that the summary for "definitely lost" now shows 80 bytes, the same as for the first memleak summary above. Thus the patch memleak.patch
fixes the memleak in sage.misc.bitset.bitset_realloc
.
Apply:
Attachments (2)
Change History (6)
Changed 12 years ago by
Attachment:  trac10287_memleak.patch added 

Changed 12 years ago by
Attachment:  test.patch added 

comment:1 Changed 12 years ago by
Authors:  → Minh Van Nguyen 

Description:  modified (diff) 
Status:  new → needs_review 
comment:2 Changed 12 years ago by
Description:  modified (diff) 

comment:3 Changed 12 years ago by
Reviewers:  → Robert Miller 

Status:  needs_review → positive_review 
comment:4 Changed 12 years ago by
Merged in:  → sage4.6.1.alpha3 

Resolution:  → fixed 
Status:  positive_review → closed 