fix numerous memory leaks in the math types.
fixed bug: #1633 Memory leak in M_Mathutils_Vector The math types ( matrix, vector, quad ) now make copies of data passed to them rather than holding a pointer to memory that cannot be freed, or that may go away unexpectedly. This also clarifies the problem of who is responsible for freeing memory allocations. Pre-checkin files are tagged mem_leak-1 in case this breaks something.
This commit is contained in:
@@ -392,6 +392,7 @@ PyObject *Vector_add( PyObject * v1, PyObject * v2 )
|
||||
{
|
||||
float *vec;
|
||||
int x;
|
||||
PyObject *retval;
|
||||
|
||||
if( ( !VectorObject_Check( v1 ) ) || ( !VectorObject_Check( v2 ) ) )
|
||||
return EXPP_ReturnPyObjError( PyExc_TypeError,
|
||||
@@ -413,15 +414,18 @@ PyObject *Vector_add( PyObject * v1, PyObject * v2 )
|
||||
( ( VectorObject * ) v2 )->vec[x];
|
||||
}
|
||||
|
||||
return ( PyObject * ) newVectorObject( vec,
|
||||
( ( ( VectorObject * ) v1 )->
|
||||
size ) );
|
||||
retval = ( PyObject * ) newVectorObject( vec,
|
||||
( ( ( VectorObject * ) v1 )->
|
||||
size ) );
|
||||
PyMem_Free( vec );
|
||||
return retval;
|
||||
}
|
||||
|
||||
PyObject *Vector_sub( PyObject * v1, PyObject * v2 )
|
||||
{
|
||||
float *vec;
|
||||
int x;
|
||||
PyObject *retval;
|
||||
|
||||
if( ( !VectorObject_Check( v1 ) ) || ( !VectorObject_Check( v2 ) ) )
|
||||
return EXPP_ReturnPyObjError( PyExc_TypeError,
|
||||
@@ -443,15 +447,18 @@ PyObject *Vector_sub( PyObject * v1, PyObject * v2 )
|
||||
( ( VectorObject * ) v2 )->vec[x];
|
||||
}
|
||||
|
||||
return ( PyObject * ) newVectorObject( vec,
|
||||
( ( ( VectorObject * ) v1 )->
|
||||
size ) );
|
||||
retval = ( PyObject * ) newVectorObject( vec,
|
||||
( ( ( VectorObject * ) v1 )->
|
||||
size ) );
|
||||
PyMem_Free( vec );
|
||||
return retval;
|
||||
}
|
||||
|
||||
PyObject *Vector_mul( PyObject * v1, PyObject * v2 )
|
||||
{
|
||||
float *vec;
|
||||
int x;
|
||||
PyObject *retval;
|
||||
|
||||
if( ( !VectorObject_Check( v1 ) ) || ( !VectorObject_Check( v2 ) ) )
|
||||
return EXPP_ReturnPyObjError( PyExc_TypeError,
|
||||
@@ -473,15 +480,18 @@ PyObject *Vector_mul( PyObject * v1, PyObject * v2 )
|
||||
( ( VectorObject * ) v2 )->vec[x];
|
||||
}
|
||||
|
||||
return ( PyObject * ) newVectorObject( vec,
|
||||
( ( ( VectorObject * ) v1 )->
|
||||
size ) );
|
||||
retval = ( PyObject * ) newVectorObject( vec,
|
||||
( ( ( VectorObject * ) v1 )->
|
||||
size ) );
|
||||
PyMem_Free( vec );
|
||||
return retval;
|
||||
}
|
||||
|
||||
PyObject *Vector_div( PyObject * v1, PyObject * v2 )
|
||||
{
|
||||
float *vec;
|
||||
int x;
|
||||
PyObject *retval;
|
||||
|
||||
if( ( !VectorObject_Check( v1 ) ) || ( !VectorObject_Check( v2 ) ) )
|
||||
return EXPP_ReturnPyObjError( PyExc_TypeError,
|
||||
@@ -507,9 +517,11 @@ PyObject *Vector_div( PyObject * v1, PyObject * v2 )
|
||||
( ( VectorObject * ) v2 )->vec[x];
|
||||
}
|
||||
|
||||
return ( PyObject * ) newVectorObject( vec,
|
||||
( ( ( VectorObject * ) v1 )->
|
||||
size ) );
|
||||
retval = ( PyObject * ) newVectorObject( vec,
|
||||
( ( ( VectorObject * ) v1 )->
|
||||
size ) );
|
||||
PyMem_Free( vec );
|
||||
return retval;
|
||||
}
|
||||
|
||||
//coercion of unknown types to type VectorObject for numeric protocols
|
||||
@@ -522,7 +534,7 @@ int Vector_coerce( PyObject ** v1, PyObject ** v2 )
|
||||
|
||||
if( VectorObject_Check( *v1 ) ) {
|
||||
if( VectorObject_Check( *v2 ) ) { //two vectors
|
||||
Py_INCREF( *v1 );
|
||||
Py_INCREF( *v1 ); /* fixme: wahy are we bumping the ref count? */
|
||||
Py_INCREF( *v2 );
|
||||
return 0;
|
||||
} else {
|
||||
@@ -540,9 +552,8 @@ int Vector_coerce( PyObject ** v1, PyObject ** v2 )
|
||||
v1 )->size ) *
|
||||
sizeof( float ) );
|
||||
for( x = 0;
|
||||
x <
|
||||
( ( ( VectorObject * ) *
|
||||
v1 )->size ); x++ ) {
|
||||
x < ( ( ( VectorObject * ) * v1 )->size );
|
||||
x++ ) {
|
||||
vec[x] = ( float ) *tempI;
|
||||
}
|
||||
PyMem_Free( tempI );
|
||||
@@ -641,11 +652,19 @@ PyTypeObject vector_Type = {
|
||||
|
||||
|
||||
/*
|
||||
* create a Vector Object
|
||||
* if vec arg is NULL
|
||||
* allocate memory on python stack.
|
||||
* initialize to zero in homogenous coords.
|
||||
* create a Vector Object( vec, size )
|
||||
*
|
||||
* Note: Vector now uses copy semantics like STL containers.
|
||||
* Memory for vec member is allocated on python stack.
|
||||
* We own this memory and will free it later.
|
||||
*
|
||||
* size arg is number of floats to alloc.
|
||||
*
|
||||
* if vec arg is NULL
|
||||
* fill our vec with zeros
|
||||
* initialize 4d vectors to zero in homogenous coords.
|
||||
* else
|
||||
* vec param is copied into our local memory and always freed.
|
||||
*/
|
||||
|
||||
PyObject *newVectorObject( float *vec, int size )
|
||||
@@ -657,17 +676,19 @@ PyObject *newVectorObject( float *vec, int size )
|
||||
|
||||
self = PyObject_NEW( VectorObject, &vector_Type );
|
||||
|
||||
self->vec = PyMem_Malloc( size * sizeof( float ) );
|
||||
self->delete_pymem = 1; /* must free this alloc later */
|
||||
|
||||
if( !vec ) {
|
||||
self->vec = PyMem_Malloc( size * sizeof( float ) );
|
||||
for( x = 0; x < size; x++ ) {
|
||||
self->vec[x] = 0.0f;
|
||||
}
|
||||
if( size == 4 )
|
||||
if( size == 4 ) /* do the homogenous thing */
|
||||
self->vec[3] = 1.0f;
|
||||
self->delete_pymem = 1; /* must free this alloc later */
|
||||
} else {
|
||||
self->vec = vec;
|
||||
self->delete_pymem = 0;
|
||||
for( x = 0; x < size; x++ ){
|
||||
self->vec[x] = vec[x];
|
||||
}
|
||||
}
|
||||
|
||||
self->size = size;
|
||||
|
||||
Reference in New Issue
Block a user