[PyQt] SIP: memory leak in mapped type?

Phil Thompson phil at riverbankcomputing.co.uk
Fri Jul 27 14:19:44 BST 2007


On Tuesday 24 July 2007 3:45 pm, Giovanni Bajo wrote:
> Hi,
>
> this is some mapped code I have written:
>
> ========================================================================
> template<TYPE>
> %MappedType std::vector<TYPE>
> {
> %TypeHeaderCode
> #include <vector>
> %End
>
> %ConvertFromTypeCode
>      PyObject *l;
>
>      // Create the Python list of the correct length.
>      if ((l = PyList_New(sipCpp -> size())) == NULL)
>          return NULL;
>
>      // Go through each element in the C++ instance and convert it to a
>      // wrapped P2d.
>      for (int i = 0; i < (int)sipCpp -> size(); ++i)
>      {
>          TYPE *cpp = new TYPE(sipCpp -> at(i));
>          PyObject *pobj;
>
>          // Get the Python wrapper for the Type instance, creating a new
>          // one if necessary, and handle any ownership transfer.
>          if ((pobj = sipConvertFromInstance(cpp, sipClass_TYPE,
> sipTransferObj)) == NULL)

Using sipConvertNewFromInstance() is preferable.

>          {
>              // There was an error so garbage collect the Python list.
>              Py_DECREF(l);

delete cpp?

>              return NULL;
>          }
>
>          // Add the wrapper to the list.
>          PyList_SET_ITEM(l, i, pobj);
>      }
>
>      // Return the Python list.
>      return l;
> %End
> ========================================================================
>
> It's part of a stl.sip I have posted in full some months ago, and it's
> very similar to the sample code in the SIP documentation. Now, I found
> out that this code causes memory leaks, which can be fixed with this
> simple patch:
>
>
> -        if ((pobj = sipConvertFromInstance(cpp, sipClass_TYPE,
> sipTransferObj)) == NULL)
> +        if ((pobj = sipConvertFromInstance(cpp, sipClass_TYPE,
> Py_None)) == NULL)
>
>
> But then, I was wondering about the semantic of sipTransferObj. The
> documentation isn't very clear about its usage. In fact, it's not clear
> in this case whether it should apply to the whole vectors or to the
> individual objects in the vector.

What it applies to is entirely up to you. In PyQt it always applies to the 
individual elements.

> Does the fix make sense?

No.

> And if so, why it isn't required in the SIP 
> documentation example? And finally, with the above patch, the value of
> sipTransferObj is totally ignored by the code: how can that be right?

For it to have any effect you must have used one of the Transfer annotations 
on an argument or result of type std::vector<>. That will cause extra element 
references to be taken - maybe that's not appropriate?

Phil


More information about the PyQt mailing list