[PyQt] double free issue with OUT-argument

Diez B. Roggisch deets at web.de
Sat Feb 13 17:34:58 GMT 2010


Hi,

wrapping happily away a 3D-engine, I encounter the following problem:

 >>> import irrlicht
 >>> core = irrlicht.irr.core
 >>> q = core.quaternion()
 >>> q.toEuler()
python(3701) malloc: *** error for object 0x474b70: double free
*** set a breakpoint in malloc_error_break to debug
(0.0, -0.0, 0.0)


This is the declaration of toEuler in .sip:

       void toEuler(irr::core::vector3df& euler /Out/) const;

As you can see, it's supposed to modify a passed vector in place. 
However, I declared vectors to be converted from & to tuples, by this 
code mapping:

%MappedType irr::core::vector3df
{
%TypeHeaderCode
#include <vector3d.h>
%End

%ConvertFromTypeCode
   if (!sipCpp)
     return PyTuple_New(0);
   irr::core::vector3df *v = (irr::core::vector3df *)sipCpp;
   return PyTuple_Pack(3, 
PyFloat_FromDouble(v->X),PyFloat_FromDouble(v->Y),PyFloat_FromDouble(v->Z));
%End

%ConvertToTypeCode
    if (sipIsErr == NULL) {
      if(PySequence_Check(sipPy) && PySequence_Length(sipPy) == 3) {
        for(int j = 0; j < 3; j++) {
	 PyObject *v = PySequence_GetItem(sipPy, j);
	 if(!PyFloat_Check(v) && !PyInt_Check(v)) {
	   return false;
	 }
        }
        return true;
      }
      return false;
    }
   if (sipPy == Py_None) {
     *sipCppPtr = NULL;
     return 0;
   }

   irr::core::vector3df *v = new irr::core::vector3df();
   PyErr_Clear();
   irr::core::vector3df &t = *v;
   if(PyArg_ParseTuple(sipPy, "fff", &t.X, &t.Y, &t.Z)) {
     *sipCppPtr = v;
     return 1;
   } else {
     delete v;
     *sipIsErr = 1;
     return 0;
   }
%End
};

Looking at the generated code, it seems to me it is perfectly fine - it 
creates a new vector instance, passes that in, converts it to a tuple, 
and deletes it.

extern "C" {static PyObject *meth_irr_core_quaternion_toEuler(PyObject 
*, PyObject *);}
static PyObject *meth_irr_core_quaternion_toEuler(PyObject *sipSelf, 
PyObject *sipArgs)
{
     int sipArgsParsed = 0;

     {
         irr::core::vector3df * a0;
         irr::core::quaternion *sipCpp;

         if 
(sipParseArgs(&sipArgsParsed,sipArgs,"B",&sipSelf,sipType_irr_core_quaternion,&sipCpp))
         {
             PyObject *sipResult;
             a0 = new irr::core::vector3df();

             sipCpp->toEuler(*a0);

             sipResult = 
sipConvertFromNewType(a0,sipType_irr_core_vector3df,NULL);
             delete a0;

             return sipResult;
         }
     }

     /* Raise an exception if the arguments couldn't be parsed. */
     sipNoMethod(sipArgsParsed,sipName_quaternion,sipName_toEuler);

     return NULL;
}


I don't understand the behavior - anything I miss?

Regards,

Diez


More information about the PyQt mailing list