memory leaks fixed

This commit is contained in:
Uwe Rathmann 2023-04-20 19:05:38 +02:00
parent b5d7c4cb26
commit 6a3e1d4dd5
2 changed files with 77 additions and 57 deletions

View File

@ -14,16 +14,6 @@ QSK_QT_PRIVATE_BEGIN
#include <private/qobject_p.h> #include <private/qobject_p.h>
QSK_QT_PRIVATE_END QSK_QT_PRIVATE_END
static inline void qskInvokeFunctionQueued(
QObject* object, QskMetaFunction::FunctionCall* functionCall,
void* argv[], QSemaphore* semaphore )
{
auto event = new QMetaCallEvent(
functionCall, nullptr, 0, argv, semaphore );
QCoreApplication::postEvent( object, event );
}
namespace namespace
{ {
using FunctionCall = QskMetaFunction::FunctionCall; using FunctionCall = QskMetaFunction::FunctionCall;
@ -216,7 +206,10 @@ void QskMetaFunction::invoke( QObject* object,
QSemaphore semaphore; QSemaphore semaphore;
qskInvokeFunctionQueued( receiver, m_functionCall, argv, &semaphore ); auto event = new QMetaCallEvent(
m_functionCall, nullptr, 0, argv, &semaphore );
QCoreApplication::postEvent( receiver, event );
semaphore.acquire(); semaphore.acquire();
@ -225,18 +218,22 @@ void QskMetaFunction::invoke( QObject* object,
case Qt::QueuedConnection: case Qt::QueuedConnection:
{ {
if ( receiver.isNull() ) if ( receiver.isNull() )
{
return; return;
}
const auto argc = parameterCount() + 1; // return value + arguments const auto argc = parameterCount() + 1; // return value + arguments
auto arguments = static_cast< void** >( std::malloc( argc * sizeof( void* ) ) ); auto event = new QMetaCallEvent( m_functionCall, nullptr, 0, argc );
if ( arguments == nullptr ) auto types = event->types();
return; auto arguments = event->args();
#if QT_VERSION >= QT_VERSION_CHECK( 6, 0, 0 )
types[0] = QMetaType();
arguments[ 0 ] = nullptr; arguments[ 0 ] = nullptr;
#else
types[0] = 0;
arguments[ 0 ] = nullptr;
#endif
const int* parameterTypes = m_functionCall->parameterTypes(); const int* parameterTypes = m_functionCall->parameterTypes();
for ( uint i = 1; i < argc; i++ ) for ( uint i = 1; i < argc; i++ )
@ -248,24 +245,22 @@ void QskMetaFunction::invoke( QObject* object,
break; break;
} }
const auto type = parameterTypes[ i - 1 ]; const auto type = parameterTypes[i - 1];
arguments[ i ] =
#if QT_VERSION >= QT_VERSION_CHECK( 6, 0, 0 ) #if QT_VERSION >= QT_VERSION_CHECK( 6, 0, 0 )
QMetaType( type ).create( argv[ i ] ); types[ i ] = QMetaType( type );
arguments[ i ] = QMetaType( type ).create( argv[ i ] );
#else #else
QMetaType::create( type, argv[ i ] ); types[ i ] = type;
arguments[ i ] = QMetaType::create( type, argv[ i ] );
#endif #endif
} }
if ( receiver.isNull() ) if ( receiver )
{ QCoreApplication::postEvent( receiver, event );
// object might have died in the meantime else
std::free( arguments ); delete event;
return;
}
qskInvokeFunctionQueued( object, m_functionCall, arguments, nullptr );
break; break;
} }
} }

View File

@ -60,12 +60,22 @@ namespace
class MetaCallEvent final : public QMetaCallEvent class MetaCallEvent final : public QMetaCallEvent
{ {
public: public:
MetaCallEvent( MetaCallEvent( QMetaObject::Call call, const QMetaObject* metaObject,
QMetaObject::Call call, CallFunction callFunction, ushort offset, ushort offset, ushort index, void* args[], QSemaphore* semaphore )
ushort index, void* args[], QSemaphore* semaphore ) : QMetaCallEvent( offset, index,
: QMetaCallEvent( offset, index, callFunction, nullptr, -1, args, semaphore ) metaObject->d.static_metacall, nullptr, -1, args, semaphore )
, m_call( call ) , m_call( call )
, m_callFunction( callFunction ) , m_callFunction( metaObject->d.static_metacall )
, m_index( index )
{
}
MetaCallEvent( QMetaObject::Call call, const QMetaObject* metaObject,
ushort offset, ushort index, int argc )
: QMetaCallEvent( offset, index,
metaObject->d.static_metacall, nullptr, -1, argc )
, m_call( call )
, m_callFunction( metaObject->d.static_metacall )
, m_index( index ) , m_index( index )
{ {
} }
@ -88,7 +98,7 @@ static inline void qskInvokeMetaCallQueued( QObject* object,
const QMetaObject* metaObject, QMetaObject::Call call, ushort offset, const QMetaObject* metaObject, QMetaObject::Call call, ushort offset,
ushort index, void* args[], QSemaphore* semaphore ) ushort index, void* args[], QSemaphore* semaphore )
{ {
auto event = new MetaCallEvent( call, metaObject->d.static_metacall, auto event = new MetaCallEvent( call, metaObject,
offset, index, args, semaphore ); offset, index, args, semaphore );
QCoreApplication::postEvent( object, event ); QCoreApplication::postEvent( object, event );
@ -194,9 +204,11 @@ static void qskInvokeMetaCall(
QSemaphore semaphore; QSemaphore semaphore;
qskInvokeMetaCallQueued( receiver, metaObject, call, auto event = new MetaCallEvent( call, metaObject,
offset, index, argv, &semaphore ); offset, index, argv, &semaphore );
QCoreApplication::postEvent( receiver, event );
semaphore.acquire(); semaphore.acquire();
break; break;
@ -206,7 +218,7 @@ static void qskInvokeMetaCall(
if ( receiver == nullptr ) if ( receiver == nullptr )
return; return;
void** arguments = nullptr; MetaCallEvent* event = nullptr;
if ( call == QMetaObject::InvokeMetaMethod ) if ( call == QMetaObject::InvokeMetaMethod )
{ {
@ -216,15 +228,23 @@ static void qskInvokeMetaCall(
#endif #endif
const int argc = method.parameterCount() + 1; const int argc = method.parameterCount() + 1;
arguments = static_cast< void** >( malloc( argc * sizeof( void* ) ) ); event = new MetaCallEvent( call, metaObject, offset, index, argc );
/* /*
The first one is the return type, one that is always The first one is the return type, one that is always
invalid for Queued Connections. invalid for Queued Connections.
*/ */
arguments[ 0 ] = nullptr; auto types = event->types();
auto arguments = event->args();
#if QT_VERSION >= QT_VERSION_CHECK( 6, 0, 0 )
types[0] = QMetaType();
arguments[ 0 ] = nullptr;
#else
types[0] = 0;
arguments[ 0 ] = nullptr;
#endif
for ( int i = 1; i < argc; i++ ) for ( int i = 1; i < argc; i++ )
{ {
if ( argv[ i ] == nullptr ) if ( argv[ i ] == nullptr )
@ -235,7 +255,15 @@ static void qskInvokeMetaCall(
} }
const auto type = method.parameterType( i - 1 ); const auto type = method.parameterType( i - 1 );
arguments[ i ] = qskMetaTypeCreate( type, argv[ i ] ); const auto arg = argv[ i ];
#if QT_VERSION >= QT_VERSION_CHECK( 6, 0, 0 )
types[ i ] = QMetaType( type );
arguments[ i ] = QMetaType( type ).create( arg );
#else
types[ i ] = type;
arguments[ i ] = QMetaType::create( type, arg );
#endif
} }
} }
else else
@ -243,27 +271,24 @@ static void qskInvokeMetaCall(
// should be doable without QMetaMethod. TODO ... // should be doable without QMetaMethod. TODO ...
const auto property = metaObject->property( offset + index ); const auto property = metaObject->property( offset + index );
arguments = static_cast< void** >( malloc( 1 * sizeof( void* ) ) ); event = new MetaCallEvent( call, metaObject, offset, index, 1 );
arguments[ 0 ] = qskMetaTypeCreate( property.userType(), argv[ 0 ] );
const auto type = property.userType();
const auto arg = argv[ 0 ];
#if QT_VERSION >= QT_VERSION_CHECK( 6, 0, 0 )
event->types()[0] = QMetaType( type );
event->args()[ 0 ] = QMetaType( type ).create( arg );
#else
event->types()[0] = type;
event->args()[ 0 ] = QMetaType::create( type, arg );
#endif
} }
if ( receiver.isNull() ) if ( receiver )
{ QCoreApplication::postEvent( receiver, event );
/* else
receiver might have died in the meantime. delete event;
We create a dummy event, so that the arguments
are freed by its destructor.
*/
const MetaCallEvent cleanUpEvent(
call, metaObject->d.static_metacall,
offset, index, arguments, nullptr );
return;
}
qskInvokeMetaCallQueued( object, metaObject,
call, offset, index, arguments, nullptr );
break; break;
} }