On Thu, Apr 10, 2008 at 9:51 AM, Brian Granger <[EMAIL PROTECTED]> wrote:
>
>  Hi,
>
>  (dual posted to sage and cython)
>
>  A few of us (ipython and mpi4py devs) are wondering what the
>  best/safest way of allocating dynamic memory in a local scope
>  (method/function) is when using cython.  An example would be if you
>  need an array of c ints that is locally scoped.
>
>  The big question is how to make sure that the memory gets freed - even
>  if something goes wrong in the function/method.  That is, you want to
>  prevent memory leaks.  It looks like in sage, the
>  sage_malloc/sage_free functions are used for this purpose:
>
>  from sage/graphs/graph_isom.pyx:
>
>    176    def incorporate_permutation(self, gamma):
>    202        cdef int *_gamma = <int *> sage_malloc( n * sizeof(int) )
>    203        if not _gamma:
>    204            raise MemoryError("Error allocating memory.")
>    205        for k from 0 <= k < n:
>    206            _gamma[k] = gamma[k]
>    207        self._incorporate_permutation(_gamma, n)
>    208        sage_free(_gamma)
>
>  Because sage_malloc is #defined to malloc in stdsage.h,

> I think there
>  is a significant potential for memory leaks in code like this.  Are we
>  thinking correctly on this issue?

Yes.  In the above code one could easily cause a serious memory
leak by input a gamma so that gamma[k], for some k with 0 <= k < n,
results in an exception.

>   Isn't this a huge problem?

Yes it's a problem.

>  Lisandro Dalcin (author of mpi4py) came up with the following trick
>  that, while more complicated, prevents memory leaks:
>
>  cdef extern from "Python.h":
>     object PyString_FromStringAndSize(char*,Py_ssize_t)
>     char* PyString_AS_STRING(object)
>
>  cdef inline object pyalloc_i(int size, int **i):
>     if size < 0: size = 0
>     cdef Py_ssize_t n = size * sizeof(int)
>     cdef object ob = PyString_FromStringAndSize(NULL, n)
>     i[0] = <int*> PyString_AS_STRING(ob)
>     return ob
>
>  and now
>
>  def foo(sequence):
>     cdef int size = len(sequence),
>     cdef int *buf = NULL
>     cdef object tmp = pyalloc_i(size, &buf)
>
>  This could probably be adapted into a malloc-like function.  What do
>  people think?

Could you explain what the point is?  Is it that this is a trick so that
Cython will correctly garbage collect the allocated memory, even
if an exception occurs?

 -- William

--~--~---------~--~----~------------~-------~--~----~
To post to this group, send email to sage-devel@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at http://groups.google.com/group/sage-devel
URLs: http://www.sagemath.org
-~----------~----~----~----~------~----~------~--~---

Reply via email to