[PyQt] double free issue with OUT-argument
Phil Thompson
phil at riverbankcomputing.com
Mon Feb 15 11:36:12 GMT 2010
On Sat, 13 Feb 2010 18:34:58 +0100, "Diez B. Roggisch" <deets at web.de>
wrote:
> 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?
Which version of SIP? I think this is fixed in SIP v4.10.
Unrelated...
There is a memory leak in your %ConvertToTypeCode as PySequence_GetItem()
returns a new reference to the item. However you should use the PyTuple
functions anyway (which don't return a new reference) because you are using
PyArg_ParseTuple() to do the conversion.
Phil
More information about the PyQt
mailing list