From 2ecdb7fd8bb88e1cd1e7c1147c8578bf2e6fa465 Mon Sep 17 00:00:00 2001 From: pgScorpio Date: Tue, 26 Apr 2022 21:42:50 +0200 Subject: [PATCH 1/4] Fixing memory leaks. Moved pointers to with new assigned objects outside main and added a cleanup function that is called before every exit to delete those objects again. --- src/main.cpp | 78 ++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 66 insertions(+), 12 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 86a37e40e3..0e22787cd5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -55,6 +55,42 @@ extern void qt_set_sequence_auto_mnemonic ( bool bEnable ); // Implementation ************************************************************** +// NOTE: To prevent memory leaks any pointers assigned with new +// should be declared here and checked and deleted in reverse order of creation in cleanup(). +// cleanup() should be called before any exit() ! + +QCoreApplication* pApp = NULL; +CRpcServer* pRpcServer = NULL; +CClientRpc* pClientRpc = NULL; +CServerRpc* pServerRpc = NULL; + +void cleanup() +{ + if ( pServerRpc ) + { + delete pServerRpc; + pServerRpc = NULL; + } + + if ( pClientRpc ) + { + delete pClientRpc; + pClientRpc = NULL; + } + + if ( pRpcServer ) + { + delete pRpcServer; + pRpcServer = NULL; + } + + if ( pApp ) + { + delete pApp; + pApp = NULL; + } +} + int main ( int argc, char** argv ) { @@ -63,6 +99,7 @@ int main ( int argc, char** argv ) // Qt will not show these with underline characters in the GUI on MacOS. (#1873) qt_set_sequence_auto_mnemonic ( true ); #endif + int exit_code = 0; QString strArgument; double rDbleArgument; @@ -136,6 +173,7 @@ int main ( int argc, char** argv ) { const QString strHelp = UsageArguments ( argv ); std::cout << qUtf8Printable ( strHelp ); + cleanup(); exit ( 0 ); } @@ -143,6 +181,7 @@ int main ( int argc, char** argv ) if ( ( !strcmp ( argv[i], "--version" ) ) || ( !strcmp ( argv[i], "-v" ) ) ) { std::cout << qUtf8Printable ( GetVersionAndNameStr ( false ) ); + cleanup(); exit ( 0 ); } @@ -563,6 +602,7 @@ int main ( int argc, char** argv ) // clicking on the Mac application bundle, the actual application // is called with weird command line args -> do not exit on these #if !( defined( Q_OS_MACX ) ) + cleanup(); exit ( 1 ); #endif } @@ -584,6 +624,7 @@ int main ( int argc, char** argv ) if ( bIsClient ) { qCritical() << "Only --server mode is supported in this build."; + cleanup(); exit ( 1 ); } #endif @@ -598,6 +639,7 @@ int main ( int argc, char** argv ) qCritical() << qUtf8Printable ( QString ( "%1: Server only option(s) '%2' used. Did you omit '--server'?" ) .arg ( argv[0] ) .arg ( ServerOnlyOptions.join ( ", " ) ) ); + cleanup(); exit ( 1 ); } @@ -622,6 +664,7 @@ int main ( int argc, char** argv ) { qCritical() << qUtf8Printable ( QString ( "%1: Client only option(s) '%2' used. See '--help' for help" ).arg ( argv[0] ).arg ( ClientOnlyOptions.join ( ", " ) ) ); + cleanup(); exit ( 1 ); } @@ -768,9 +811,9 @@ int main ( int argc, char** argv ) bIsClient = true; // Client only - TODO: maybe a switch in interface to change to server? // bUseMultithreading = true; - QApplication* pApp = new QApplication ( argc, argv ); + pApp = new QApplication ( argc, argv ); # else - QCoreApplication* pApp = bUseGUI ? new QApplication ( argc, argv ) : new QCoreApplication ( argc, argv ); + pApp = bUseGUI ? new QApplication ( argc, argv ) : new QCoreApplication ( argc, argv ); # endif #endif @@ -818,13 +861,12 @@ int main ( int argc, char** argv ) // clang-format on #endif - CRpcServer* pRpcServer = nullptr; - if ( iJsonRpcPortNumber != INVALID_PORT ) { if ( strJsonRpcSecretFileName.isEmpty() ) { qCritical() << qUtf8Printable ( QString ( "- JSON-RPC: --jsonrpcsecretfile is required. Exiting." ) ); + cleanup(); exit ( 1 ); } @@ -832,6 +874,7 @@ int main ( int argc, char** argv ) if ( !qfJsonRpcSecretFile.open ( QFile::OpenModeFlag::ReadOnly ) ) { qCritical() << qUtf8Printable ( QString ( "- JSON-RPC: Unable to open secret file %1. Exiting." ).arg ( strJsonRpcSecretFileName ) ); + cleanup(); exit ( 1 ); } QTextStream qtsJsonRpcSecretStream ( &qfJsonRpcSecretFile ); @@ -841,6 +884,7 @@ int main ( int argc, char** argv ) qCritical() << qUtf8Printable ( QString ( "JSON-RPC: Refusing to run with secret of length %1 (required: %2). Exiting." ) .arg ( strJsonRpcSecret.length() ) .arg ( JSON_RPC_MINIMUM_SECRET_LENGTH ) ); + cleanup(); exit ( 1 ); } @@ -851,6 +895,7 @@ int main ( int argc, char** argv ) if ( !pRpcServer->Start() ) { qCritical() << qUtf8Printable ( QString ( "- JSON-RPC: Server failed to start. Exiting." ) ); + cleanup(); exit ( 1 ); } } @@ -884,7 +929,7 @@ int main ( int argc, char** argv ) if ( pRpcServer ) { - new CClientRpc ( &Client, pRpcServer, pRpcServer ); + pClientRpc = new CClientRpc ( &Client, pRpcServer, pRpcServer ); } # ifndef HEADLESS @@ -903,7 +948,7 @@ int main ( int argc, char** argv ) // show dialog ClientDlg.show(); - pApp->exec(); + exit_code = pApp->exec(); } else # endif @@ -911,7 +956,7 @@ int main ( int argc, char** argv ) // only start application without using the GUI qInfo() << qUtf8Printable ( GetVersionAndNameStr ( false ) ); - pApp->exec(); + exit_code = pApp->exec(); } } else @@ -942,7 +987,7 @@ int main ( int argc, char** argv ) if ( pRpcServer ) { - new CServerRpc ( &Server, pRpcServer, pRpcServer ); + pServerRpc = new CServerRpc ( &Server, pRpcServer, pRpcServer ); } #ifndef HEADLESS @@ -967,7 +1012,7 @@ int main ( int argc, char** argv ) ServerDlg.show(); } - pApp->exec(); + exit_code = pApp->exec(); } else #endif @@ -982,7 +1027,7 @@ int main ( int argc, char** argv ) Server.SetDirectoryType ( AT_CUSTOM ); } - pApp->exec(); + exit_code = pApp->exec(); } } } @@ -999,7 +1044,11 @@ int main ( int argc, char** argv ) #endif { qCritical() << qUtf8Printable ( QString ( "%1: %2" ).arg ( APP_NAME ).arg ( generr.GetErrorText() ) ); - exit ( 1 ); + + if ( exit_code == 0 ) + { + exit_code = 1; + } } } @@ -1007,7 +1056,9 @@ int main ( int argc, char** argv ) activity.EndActivity(); #endif - return 0; + cleanup(); + + return exit_code; } /******************************************************************************\ @@ -1102,6 +1153,7 @@ bool GetStringArgument ( int argc, char** argv, int& i, QString strShortOpt, QSt if ( ++i >= argc ) { qCritical() << qUtf8Printable ( QString ( "%1: '%2' needs a string argument." ).arg ( argv[0] ).arg ( argv[i - 1] ) ); + cleanup(); exit ( 1 ); } @@ -1130,6 +1182,7 @@ bool GetNumericArgument ( int argc, if ( ++i >= argc ) { qCritical() << qUtf8Printable ( errmsg.arg ( argv[0] ).arg ( argv[i - 1] ).arg ( rRangeStart ).arg ( rRangeStop ) ); + cleanup(); exit ( 1 ); } @@ -1138,6 +1191,7 @@ bool GetNumericArgument ( int argc, if ( *p || ( rValue < rRangeStart ) || ( rValue > rRangeStop ) ) { qCritical() << qUtf8Printable ( errmsg.arg ( argv[0] ).arg ( argv[i - 1] ).arg ( rRangeStart ).arg ( rRangeStop ) ); + cleanup(); exit ( 1 ); } From affd49d241143aabfc16c99b3bf638daa001a6e4 Mon Sep 17 00:00:00 2001 From: pgScorpio Date: Tue, 26 Apr 2022 23:02:50 +0200 Subject: [PATCH 2/4] Bugfix pClientRpc does not exist in server-only mode --- src/main.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 0e22787cd5..91244fb3ba 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -61,8 +61,10 @@ extern void qt_set_sequence_auto_mnemonic ( bool bEnable ); QCoreApplication* pApp = NULL; CRpcServer* pRpcServer = NULL; -CClientRpc* pClientRpc = NULL; -CServerRpc* pServerRpc = NULL; +#ifndef SERVER_ONLY +CClientRpc* pClientRpc = NULL; +#endif +CServerRpc* pServerRpc = NULL; void cleanup() { @@ -72,11 +74,13 @@ void cleanup() pServerRpc = NULL; } +#ifndef SERVER_ONLY if ( pClientRpc ) { delete pClientRpc; pClientRpc = NULL; } +#endif if ( pRpcServer ) { From e090359cd29c816b76fef3bab1ef063f138e2d79 Mon Sep 17 00:00:00 2001 From: pgScorpio Date: Tue, 26 Apr 2022 23:50:20 +0200 Subject: [PATCH 3/4] Bugfix headless mode Forgot to use the right pApp pointer in headless mode. --- src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index 91244fb3ba..91e6c0c60a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -808,7 +808,7 @@ int main ( int argc, char** argv ) // Application/GUI setup --------------------------------------------------- // Application object #ifdef HEADLESS - QCoreApplication* pApp = new QCoreApplication ( argc, argv ); + pApp = new QCoreApplication ( argc, argv ); #else # if defined( Q_OS_IOS ) bUseGUI = true; From e8c1a21a24ce0b188199a9bf269d9b6eb4b18987 Mon Sep 17 00:00:00 2001 From: pgScorpio Date: Wed, 27 Apr 2022 17:11:54 +0200 Subject: [PATCH 4/4] Bugfixes pApp pointer type and exit_code --- src/main.cpp | 44 ++++++++++++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 91e6c0c60a..56b177fc16 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -59,8 +59,10 @@ extern void qt_set_sequence_auto_mnemonic ( bool bEnable ); // should be declared here and checked and deleted in reverse order of creation in cleanup(). // cleanup() should be called before any exit() ! -QCoreApplication* pApp = NULL; -CRpcServer* pRpcServer = NULL; +QCoreApplication* pCoreApplicationInstance = NULL; +QApplication* pApplicationInstance = NULL; + +CRpcServer* pRpcServer = NULL; #ifndef SERVER_ONLY CClientRpc* pClientRpc = NULL; #endif @@ -88,10 +90,16 @@ void cleanup() pRpcServer = NULL; } - if ( pApp ) + if ( pCoreApplicationInstance ) { - delete pApp; - pApp = NULL; + delete pCoreApplicationInstance; + pCoreApplicationInstance = NULL; + } + + if ( pApplicationInstance ) + { + delete pApplicationInstance; + pApplicationInstance = NULL; } } @@ -808,16 +816,24 @@ int main ( int argc, char** argv ) // Application/GUI setup --------------------------------------------------- // Application object #ifdef HEADLESS - pApp = new QCoreApplication ( argc, argv ); + QCoreApplication* pApp = pCoreApplicationInstance = new QCoreApplication ( argc, argv ); #else # if defined( Q_OS_IOS ) bUseGUI = true; bIsClient = true; // Client only - TODO: maybe a switch in interface to change to server? // bUseMultithreading = true; - pApp = new QApplication ( argc, argv ); + QApplication* pApp = pApplicationInstance = new QApplication ( argc, argv ); # else - pApp = bUseGUI ? new QApplication ( argc, argv ) : new QCoreApplication ( argc, argv ); + QCoreApplication* pApp; + if ( bUseGUI ) + { + pApp = pApplicationInstance = new QApplication ( argc, argv ); + } + else + { + pApp = pCoreApplicationInstance = new QCoreApplication ( argc, argv ); + } # endif #endif @@ -1048,18 +1064,14 @@ int main ( int argc, char** argv ) #endif { qCritical() << qUtf8Printable ( QString ( "%1: %2" ).arg ( APP_NAME ).arg ( generr.GetErrorText() ) ); + } - if ( exit_code == 0 ) - { - exit_code = 1; - } + if ( exit_code == 0 ) + { + exit_code = 1; } } -#if defined( Q_OS_MACX ) - activity.EndActivity(); -#endif - cleanup(); return exit_code;