Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do I not need to free this memory?

I'm writing a Python C extension, and in the examples listed here, there is a snippet of code:

static PyObject * spam_system(PyObject *self, PyObject *args) {
    const char *command;
    int sts;

    if (!PyArg_ParseTuple(args, "s", &command)) return NULL;
    sts = system(command);
    return Py_BuildValue("i", sts);
}

According to the documentation for parsing a string with PyArg_ParseTuple, "You must not provide storage for the string itself; a pointer to an existing string is stored into the character pointer variable whose address you pass." So how does Python know when the memory pointed to by "command" can be freed? How is a memory leak not occurring?

like image 455
amoffat Avatar asked Apr 09 '11 17:04

amoffat


People also ask

What happens if I don't free memory?

If free() is not used in a program the memory allocated using malloc() will be de-allocated after completion of the execution of the program (included program execution time is relatively small and the program ends normally).

Why do we need to free memory?

However on long running programs, failing to free memory means you will be consuming a finite resource without replenishing it. Eventually it will run out and your program will rudely crash. This is why you must free memory.

What happens if you dont deallocate dynamic memory?

Objects allocated with new stay on the heap until they are deallocated with delete . If you don't delete them, they will remain there (but won't be accessible -> this is called memory leak) until your process exits, when the operating system will deallocate them.

How do I handle memory without free?

Question: How to deallocate dynamically allocate memory without using “free()” function. void * realloc ( void *ptr, size_t size); If “size” is zero, then call to realloc is equivalent to “free(ptr)”. And if “ptr” is NULL and size is non-zero then call to realloc is equivalent to “malloc(size)”.


1 Answers

The documentation says this about the "s" format specifier to PyArg_ParseTuple:

s (string or Unicode) [const char *]
Convert a Python string or Unicode object to a C pointer to a character string. You must not provide storage for the string itself; a pointer to an existing string is stored into the character pointer variable whose address you pass.

That means that the pointer is pointing to memory that Python itself is managing.

If you dig into the Python source (I'm using version 3.2) you'll find PyArg_ParseTuple in Python/getargs.c. If you trace the execution (a mark-I eyeball should be sufficient if you already know C) you'll get to convertsimple which handles some simple data type format strings (such as "s"). Then have a look at the 's' branch of the switch and you'll see this:

char **p = va_arg(*p_va, char **);
/* ... */
*p = PyBytes_AS_STRING(uarg);

And a little grepping will yield the definition of PyBytes_AS_STRING:

#define PyBytes_AS_STRING(op) (assert(PyBytes_Check(op)), \
                                (((PyBytesObject *)(op))->ob_sval))

So all this is really doing is handing you a pointer to a field, ob_sval, inside the Python object; Python is managing the memory for its internal objects.

So, you shouldn't free your command string because it ends up pointing into some of Python's internal data and Python itself is responsible for that memory. Hence the "hands off" warning in the documentation.

like image 121
mu is too short Avatar answered Oct 26 '22 16:10

mu is too short