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: sage-4.6.1
Component: memleak Keywords:
Cc: Merged in: sage-4.6.1.alpha3
Authors: Minh Van Nguyen Reviewers: Robert Miller
Report Upstream: N/A Work issues:
Branch: Commit:
Dependencies: Stopgaps:

Status badges

Description (last modified by Minh Van Nguyen)

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: --leak-check=full --show-reachable=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  
    978978    Extension('sage.misc.session',
    979979              sources = ['sage/misc/session.pyx']),
    980980
     981    Extension('sage.misc.test',
     982              sources = ['sage/misc/test.pyx']),
     983
    981984    ################################
    982985    ##
    983986    ## sage.modular
  • new file sage/misc/test.pyx

    diff --git a/sage/misc/test.pyx b/sage/misc/test.pyx
    new file mode 100644
    - +  
     1include "../ext/stdsage.pxi"
     2include "bitset_pxd.pxi"
     3include "bitset.pxi"
     4
     5def 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: --leak-check=full --show-reachable=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  
    5252    cdef unsigned long size_old = bits.size
    5353    if size_old == size: return 0
    5454    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:
    5759        bits.limbs = limbs_old
    5860        raise MemoryError
    5961    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: --leak-check=full --show-reachable=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:

  1. trac-10287_memleak.patch

Attachments (2)

trac-10287_memleak.patch (845 bytes) - added by Minh Van Nguyen 12 years ago.
test.patch (965 bytes) - added by Minh Van Nguyen 12 years ago.

Download all attachments as: .zip

Change History (6)

Changed 12 years ago by Minh Van Nguyen

Attachment: trac-10287_memleak.patch added

Changed 12 years ago by Minh Van Nguyen

Attachment: test.patch added

comment:1 Changed 12 years ago by Minh Van Nguyen

Authors: Minh Van Nguyen
Description: modified (diff)
Status: newneeds_review

comment:2 Changed 12 years ago by Minh Van Nguyen

Description: modified (diff)

comment:3 Changed 12 years ago by Robert Miller

Reviewers: Robert Miller
Status: needs_reviewpositive_review

comment:4 Changed 12 years ago by Jeroen Demeyer

Merged in: sage-4.6.1.alpha3
Resolution: fixed
Status: positive_reviewclosed
Note: See TracTickets for help on using tickets.