From 6a3e1d4dd5ccba18e79f1ddc6a3357034c142b13 Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Thu, 20 Apr 2023 19:05:38 +0200 Subject: [PATCH] memory leaks fixed --- src/common/QskMetaFunction.cpp | 49 +++++++++---------- src/common/QskMetaInvokable.cpp | 85 +++++++++++++++++++++------------ 2 files changed, 77 insertions(+), 57 deletions(-) diff --git a/src/common/QskMetaFunction.cpp b/src/common/QskMetaFunction.cpp index d73f4d9e..0eb31d39 100644 --- a/src/common/QskMetaFunction.cpp +++ b/src/common/QskMetaFunction.cpp @@ -14,16 +14,6 @@ QSK_QT_PRIVATE_BEGIN #include 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 { using FunctionCall = QskMetaFunction::FunctionCall; @@ -216,7 +206,10 @@ void QskMetaFunction::invoke( QObject* object, QSemaphore semaphore; - qskInvokeFunctionQueued( receiver, m_functionCall, argv, &semaphore ); + auto event = new QMetaCallEvent( + m_functionCall, nullptr, 0, argv, &semaphore ); + + QCoreApplication::postEvent( receiver, event ); semaphore.acquire(); @@ -225,18 +218,22 @@ void QskMetaFunction::invoke( QObject* object, case Qt::QueuedConnection: { if ( receiver.isNull() ) - { return; - } 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 ) - return; + 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 const int* parameterTypes = m_functionCall->parameterTypes(); for ( uint i = 1; i < argc; i++ ) @@ -248,24 +245,22 @@ void QskMetaFunction::invoke( QObject* object, break; } - const auto type = parameterTypes[ i - 1 ]; + const auto type = parameterTypes[i - 1]; - arguments[ i ] = #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 - QMetaType::create( type, argv[ i ] ); + types[ i ] = type; + arguments[ i ] = QMetaType::create( type, argv[ i ] ); #endif } - if ( receiver.isNull() ) - { - // object might have died in the meantime - std::free( arguments ); - return; - } + if ( receiver ) + QCoreApplication::postEvent( receiver, event ); + else + delete event; - qskInvokeFunctionQueued( object, m_functionCall, arguments, nullptr ); break; } } diff --git a/src/common/QskMetaInvokable.cpp b/src/common/QskMetaInvokable.cpp index 22a9aeba..0051e80c 100644 --- a/src/common/QskMetaInvokable.cpp +++ b/src/common/QskMetaInvokable.cpp @@ -60,12 +60,22 @@ namespace class MetaCallEvent final : public QMetaCallEvent { public: - MetaCallEvent( - QMetaObject::Call call, CallFunction callFunction, ushort offset, - ushort index, void* args[], QSemaphore* semaphore ) - : QMetaCallEvent( offset, index, callFunction, nullptr, -1, args, semaphore ) + MetaCallEvent( QMetaObject::Call call, const QMetaObject* metaObject, + ushort offset, ushort index, void* args[], QSemaphore* semaphore ) + : QMetaCallEvent( offset, index, + metaObject->d.static_metacall, nullptr, -1, args, semaphore ) , 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 ) { } @@ -88,7 +98,7 @@ static inline void qskInvokeMetaCallQueued( QObject* object, const QMetaObject* metaObject, QMetaObject::Call call, ushort offset, 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 ); QCoreApplication::postEvent( object, event ); @@ -194,9 +204,11 @@ static void qskInvokeMetaCall( QSemaphore semaphore; - qskInvokeMetaCallQueued( receiver, metaObject, call, + auto event = new MetaCallEvent( call, metaObject, offset, index, argv, &semaphore ); + QCoreApplication::postEvent( receiver, event ); + semaphore.acquire(); break; @@ -206,7 +218,7 @@ static void qskInvokeMetaCall( if ( receiver == nullptr ) return; - void** arguments = nullptr; + MetaCallEvent* event = nullptr; if ( call == QMetaObject::InvokeMetaMethod ) { @@ -216,15 +228,23 @@ static void qskInvokeMetaCall( #endif 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 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++ ) { if ( argv[ i ] == nullptr ) @@ -235,7 +255,15 @@ static void qskInvokeMetaCall( } 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 @@ -243,27 +271,24 @@ static void qskInvokeMetaCall( // should be doable without QMetaMethod. TODO ... const auto property = metaObject->property( offset + index ); - arguments = static_cast< void** >( malloc( 1 * sizeof( void* ) ) ); - arguments[ 0 ] = qskMetaTypeCreate( property.userType(), argv[ 0 ] ); + event = new MetaCallEvent( call, metaObject, offset, index, 1 ); + + 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() ) - { - /* - receiver might have died in the meantime. - 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 ); + if ( receiver ) + QCoreApplication::postEvent( receiver, event ); + else + delete event; break; }