#10287: memleak in bitset_realloc()
-------------------------------+--------------------------------------------
   Reporter:  mvngu            |       Owner:  rlm         
       Type:  defect           |      Status:  needs_review
   Priority:  major            |   Milestone:  sage-4.6.1  
  Component:  memleak          |    Keywords:              
     Author:  Minh Van Nguyen  |    Upstream:  N/A         
   Reviewer:                   |      Merged:              
Work_issues:                   |  
-------------------------------+--------------------------------------------
Description changed by mvngu:

Old description:

> See [https://groups.google.com/group/sage-
> devel/browse_thread/thread/57890c6e134a5d45 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
> [attachment:test.patch]:
>
> {{{
> #!diff
> # HG changeset patch
> # User Minh Van Nguyen <[email protected]>
> # Date 1289991585 28800
> # Node ID 0554c5d2f725c4d29a6ca0176249b3febb235be2
> # Parent  8c722bce2f917caab751122ef48b6057821142de
> imported patch test.patch
>
> diff --git a/module_list.py b/module_list.py
> --- a/module_list.py
> +++ b/module_list.py
> @@ -978,6 +978,9 @@
>      Extension('sage.misc.session',
>                sources = ['sage/misc/session.pyx']),
>
> +    Extension('sage.misc.test',
> +              sources = ['sage/misc/test.pyx']),
> +
>      ################################
>      ##
>      ## sage.modular
> diff --git a/sage/misc/test.pyx b/sage/misc/test.pyx
> new file mode 100644
> --- /dev/null
> +++ b/sage/misc/test.pyx
> @@ -0,0 +1,12 @@
> +include "../ext/stdsage.pxi"
> +include "bitset_pxd.pxi"
> +include "bitset.pxi"
> +
> +def test():
> +    cdef bitset_t a
> +    bitset_init(a, 10)
> +    try:
> +        bitset_realloc(a, 0)
> +    except MemoryError:
> +        pass
> +    bitset_free(a)
> }}}
>
> I loaded Sage under valgrind again and performed the following
> computation:
>
> {{{
> #!python
> 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:
>
> {{{
> #!diff
> # HG changeset patch
> # User Minh Van Nguyen <[email protected]>
> # 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/sage/misc/bitset.pxi
> +++ b/sage/misc/bitset.pxi
> @@ -52,8 +52,10 @@
>      cdef unsigned long size_old = bits.size
>      if size_old == size: return 0
>      bits.limbs = (size - 1)/(8*sizeof(unsigned long)) + 1
> -    bits.bits = <unsigned long*>sage_realloc(bits.bits, bits.limbs *
> sizeof(unsigned long))
> -    if bits.bits == NULL:
> +    tmp = <unsigned long*>sage_realloc(bits.bits, bits.limbs *
> sizeof(unsigned long))
> +    if tmp != NULL:
> +        bits.bits = tmp
> +    else:
>          bits.limbs = limbs_old
>          raise MemoryError
>      bits.size = size
> }}}
>
> I loaded Sage under valgrind a third time and performed the following
> computation, same as above:
>
> {{{
> #!python
> 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. [attachment:trac-10287_memleak.patch]

New description:

 This is part of the larger project at #7656. See
 [https://groups.google.com/group/sage-
 devel/browse_thread/thread/57890c6e134a5d45 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
 [attachment:test.patch]:

 {{{
 #!diff
 # HG changeset patch
 # User Minh Van Nguyen <[email protected]>
 # Date 1289991585 28800
 # Node ID 0554c5d2f725c4d29a6ca0176249b3febb235be2
 # Parent  8c722bce2f917caab751122ef48b6057821142de
 imported patch test.patch

 diff --git a/module_list.py b/module_list.py
 --- a/module_list.py
 +++ b/module_list.py
 @@ -978,6 +978,9 @@
      Extension('sage.misc.session',
                sources = ['sage/misc/session.pyx']),

 +    Extension('sage.misc.test',
 +              sources = ['sage/misc/test.pyx']),
 +
      ################################
      ##
      ## sage.modular
 diff --git a/sage/misc/test.pyx b/sage/misc/test.pyx
 new file mode 100644
 --- /dev/null
 +++ b/sage/misc/test.pyx
 @@ -0,0 +1,12 @@
 +include "../ext/stdsage.pxi"
 +include "bitset_pxd.pxi"
 +include "bitset.pxi"
 +
 +def test():
 +    cdef bitset_t a
 +    bitset_init(a, 10)
 +    try:
 +        bitset_realloc(a, 0)
 +    except MemoryError:
 +        pass
 +    bitset_free(a)
 }}}

 I loaded Sage under valgrind again and performed the following
 computation:

 {{{
 #!python
 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:

 {{{
 #!diff
 # HG changeset patch
 # User Minh Van Nguyen <[email protected]>
 # 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/sage/misc/bitset.pxi
 +++ b/sage/misc/bitset.pxi
 @@ -52,8 +52,10 @@
      cdef unsigned long size_old = bits.size
      if size_old == size: return 0
      bits.limbs = (size - 1)/(8*sizeof(unsigned long)) + 1
 -    bits.bits = <unsigned long*>sage_realloc(bits.bits, bits.limbs *
 sizeof(unsigned long))
 -    if bits.bits == NULL:
 +    tmp = <unsigned long*>sage_realloc(bits.bits, bits.limbs *
 sizeof(unsigned long))
 +    if tmp != NULL:
 +        bits.bits = tmp
 +    else:
          bits.limbs = limbs_old
          raise MemoryError
      bits.size = size
 }}}

 I loaded Sage under valgrind a third time and performed the following
 computation, same as above:

 {{{
 #!python
 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. [attachment:trac-10287_memleak.patch]

--

-- 
Ticket URL: <http://trac.sagemath.org/sage_trac/ticket/10287#comment:2>
Sage <http://www.sagemath.org>
Sage: Creating a Viable Open Source Alternative to Magma, Maple, Mathematica, 
and MATLAB

-- 
You received this message because you are subscribed to the Google Groups 
"sage-trac" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/sage-trac?hl=en.

Reply via email to