1

https://github.com/python/cpython/blob/master/Include/objimpl.h#L83 says

PyObject_Realloc(p != NULL, 0) does not return NULL, or free the memory at p.

PyObject_Realloc doesn't free the memory.

I've noticed a memory leak in my program which uses PyObject_Realloc every now and then.

I tried to fix it using this:

PyLongObject *new = (PyLongObject *) PyObject_Realloc(obj, new_size);
if (new == NULL) {
  return PyErr_NoMemory();
}
if (new != obj) {
  PyObject_Free(obj);
}
obj = new;

But now I get the malloc error pointer being freed was not allocated

How am I meant to make sure my program doesn't leak memory when using PyObject_Malloc and PyObject_Realloc?

4
  • Have you ensured that the reference count of obj is 1? If there are other pointers to it in existance then reallocing it isn't going to be safe. Commented Mar 23, 2021 at 13:01
  • 1
    @DavidW checking Py_REFCNT(obj) before every reallocation shows it's always 1 Commented Mar 23, 2021 at 13:28
  • That's fine then. There's definitely cases where this this is reliably true (e.g. you've just allocated an object in C and haven't yet returned it to Python) Commented Mar 23, 2021 at 13:47
  • @DavidW since I think the memory leak comes from elsewhere, I made a new question with my full code. I wonder if you can spot anything: stackoverflow.com/q/66764918/3310334 Commented Mar 23, 2021 at 14:16

1 Answer 1

2

You need to use this in the exact same manner as realloc must be used:

PyObject *new = PyObject_Realloc(obj, new_size);

if (new == NULL) {
    // obj is still valid - so maybe you need to free it *here*
    PyObject_Free(obj);
    return PyErr_NoMemory();
}


// if a non-null pointer *was* returned, then obj was already
// freed and new points to the new memory area. Therefore
// assign it to obj unconditionally.
obj = new;
Sign up to request clarification or add additional context in comments.

5 Comments

"maybe you need to free it" doesn't instil confidence, what if it crashes harder after that?
"if a non-null pointer was returned, then obj was already freed" how do you know?
@minseong because that is the contract.
@minseong I would be 100 % sure that it needs to be freed there in a program written by me. WIth your program I'd be just 99 % sure. It is possible to write such a spaghetti program that it would crash if you call PyObject_Free(obj) there but work right otherwise. I can't know what you've written.
I guess the memory leak comes from elsewhere. If you have the time to spare, could you take a look at this question: stackoverflow.com/q/66764918/3310334

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.