On Apr 10, 2008, at 9:51 AM, Brian Granger 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? Isn't this a huge 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?
This is actually the same solution that popped into my mind when I first read your question, and I think it is a very good one. Using string objects is particularly interesting because the they are highly optimized (for example, the buffer allocation is done as part of the object allocation). I would probably have it take a void** rather than make an allocator specific to ints. If people like this idea, I could add such a function to Sage. Maybe it would even be worthwhile adding it to Cython (in one of the included header files). Alternatively, using a try-finally will work. If the buffers all are set to start as NULL then one just frees the non-NULL buffers at the end (so one doesn't have to keep track of where in the procedure things went wrong). - Robert --~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---