4

I am writing a Python Extension in C (on Linux (Ubuntu 14.04)) and ran into an issue with dynamic memory allocation. I searched through SO and found several posts on free() calls causing similar errors because free() tries to free memory that is not dynamically allocated. But I don't know if/how that is a problem in the code below:

#include <Python.h>
#include <stdio.h>
#include <stdlib.h>

static PyObject* tirepy_process_data(PyObject* self, PyObject *args)
{
    FILE* rawfile = NULL;
    char* rawfilename = (char *) malloc(128*sizeof(char));
    if(rawfilename == NULL)
         printf("malloc() failed.\n");
    memset(rawfilename, 0, 128);
    const int num_datapts = 0; /* Just  Some interger variable*/

    if (!PyArg_ParseTuple(args, "si", &rawfilename, &num_datapts)) {
          return NULL;
    }

    /* Here I am going top open the file, read the contents and close it again */

    printf("Raw file name is: %s \n", rawfilename);
    free(rawfilename);
    return Py_BuildValue("i", num_profiles);
}

The output is:

Raw file name is: \home\location_to_file\
*** Error in `/usr/bin/python': free(): invalid pointer: 0xb7514244 ***
samuelschaefer
  • 614
  • 2
  • 10
  • 26
  • It would be interesting to see what `PyArg_ParseTuple` does and what it expects as arguments. Also note that you can get rid of the malloc [cast](http://stackoverflow.com/a/605858/3194340) – n0p Dec 17 '14 at 16:18
  • I'd also suggest using `calloc()`. Also, the size of a char is by definition 1, as all sizes are measured in multiples of a char. Oh, and please don't `printf()` errors but signal them to the caller! – Ulrich Eckhardt Dec 17 '14 at 16:27

2 Answers2

4

According to the documentation:

These formats allow to access an object as a contiguous chunk of memory. You don’t have to provide raw storage for the returned unicode or bytes area. Also, you won’t have to release any memory yourself, except with the es, es#, et and et# formats.

(Emphasis is added by me)

So you do not need to first allocate memory with malloc(). You also do not need to free() the memory afterwards.

Your error occurs because you are trying to free memory that was provided/allocated by Python. So C (malloc/free) is unable to free it, as it is unknown to the C runtime.

Veger
  • 37,240
  • 11
  • 105
  • 116
1

Please consider the API docs for `PyArg_ParseTuple': https://docs.python.org/2/c-api/arg.html

You shall NOT pass a pointer to allocated memory, nor shall you free it afterwards.

Kamajii
  • 1,826
  • 9
  • 21