-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
memory leaks fixes in non-gui tests #1213
memory leaks fixes in non-gui tests #1213
Conversation
98f4096
to
cb31fd8
Compare
@michalkaptur For consistency with the rest of the codebase, I think it would it be better to use QScopedPointer instead of std::unique_ptr. |
I was about to suggest the same. Not for consistency, but for safety reasons. Don't use STL smart pointers, though. Use Qt smartpointers. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice findings. Thanks for sharing them! You should use QScopedPointer
s, though.
src/crypto/SymmetricCipherGcrypt.h
Outdated
@@ -49,7 +49,7 @@ class SymmetricCipherGcrypt : public SymmetricCipherBackend | |||
static int gcryptMode(SymmetricCipher::Mode mode); | |||
void setErrorString(gcry_error_t err); | |||
|
|||
gcry_cipher_hd_t m_ctx; | |||
gcry_cipher_hd_t m_ctx{nullptr}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is redundant. m_ctx
is already initialized to nullptr
within the initialization list of the constructor.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
src/format/KeePass2Repair.cpp
Outdated
@@ -29,8 +29,14 @@ KeePass2Repair::KeePass2Repair() | |||
{ | |||
} | |||
|
|||
KeePass2Repair::~KeePass2Repair() | |||
{ | |||
delete m_db; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Make m_db
a QScopedPointer
and remove this code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
src/format/KeePass2Repair.cpp
Outdated
KeePass2Repair::RepairResult KeePass2Repair::repairDatabase(QIODevice* device, const CompositeKey& key) | ||
{ | ||
delete m_db; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Call
m_db.reset(reader.readDatabase(device, key, true));
instead. Replace further deletions of m_db
within this file with QScopedPointer::reset()
as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done, but kept temporary db
object not to store the database after repair failed
tests/TestCsvParser.h
Outdated
@@ -63,7 +63,7 @@ private slots: | |||
|
|||
private: | |||
QTemporaryFile* file; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Make this a QScopedPointer
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
tests/TestCsvParser.h
Outdated
@@ -63,7 +63,7 @@ private slots: | |||
|
|||
private: | |||
QTemporaryFile* file; | |||
CsvParser* parser; | |||
std::unique_ptr<CsvParser> parser; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And this as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
tests/TestGroup.cpp
Outdated
@@ -339,7 +340,7 @@ void TestGroup::testCopyCustomIcon() | |||
|
|||
void TestGroup::testClone() | |||
{ | |||
Database* db = new Database(); | |||
std::unique_ptr<Database> db(new Database()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Replace all std::unique_ptr
s in this file with QScopedPointer
s.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done, replaced all
Could you also retarget this at |
@phoerious Why is it safer to use Qt's smartpointers than STL's? |
I think I just read you slightly wrong there. The safety part is about using smart pointers over raw pointers. I somehow read that you would choose smart pointers in general for consistency. Choosing Qt smart pointers over the STL ones is of course just about consistency. 😉 |
Ok, I'll replace the |
Yes, use Qt classes where possible. Qt is not just a GUI toolkit. |
Definitely.
I'm more like "use std wherever possible", but for the sake of consistency - I'll adapt :) |
Qt and STL are mostly compatible, but not 100%.They also have two very distinct coding styles. Using Qt everywhere keeps the code consistent and prevents any compatibility problems from the start. I don't think we use STL containers or algorithms anywhere in KeePassXC |
c4730f3
to
8af631b
Compare
src/format/KeePass2Repair.cpp
Outdated
{ | ||
return m_db; | ||
return m_db.take(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry to nag again, but I didn't see that you need to share ownership of the pointer. In this case, this should be a QSharedPointer instead of a QScopedPointer.
This method should stay const and return the QSharedPointer instead of a raw pointer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree, but I wanted to leave DatabaseOpenWidget
intact for now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we change something, we should do it properly from the start.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, got it. My goal was to enable leak_check_at_exit
ASAN check for non-gui tests, without breaking too many interfaces, and then work on other memory management issues.
Considering shared ownership: There's actually no need for KeePass2Repair
to store the database (pointer, to be exact). What do you think about returning a tuple from repairDatabase()
, consisting of RepairResult
and Database*
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I understand that. I would do the same. But KeePassXC has inherited quite some baggage from KeePassX that needs cleaning up, so in cases like this we should do things properly instead of producing more patchwork.
I had a deeper look into the repair class and agree with you: there is no need to store the database. Returning a QPair<RepairResult, QSharedPointer<Database>>
sounds like a decent solution to me.
While you are at it could you also please add
Copyright (C) 2017 KeePassXC Team <[email protected]>
to the license headers? This is missing somehow.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, thanks for assistance and understanding :) I've just pushed fixed KeePass2Repair
. Just to be clear: should this PR be merged to release/2.2.2
branch only or to both, develop
and release/2.2.2
? I'm not familiar with release/branching policy yet.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only to release/2.2.3 (not 2.2.2). That branch will be merged back into develop then. Just rebase against it and change the target of this PR, I'll take care of the rest.
I hope you also don't mind if I squash your commits into one?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm a bit stuck in leaky TestGroup.cpp unit tests after rebase. I'll deliver it soon.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alright, the changes are rebased against release/2.2.3
, squashed and green on CI 😃
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks!
src/format/KeePass2Repair.h
Outdated
QString errorString() const; | ||
|
||
private: | ||
Database* m_db; | ||
QScopedPointer<Database> m_db{nullptr}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should initialize members in the initialization list of the constructor.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do you think so? User defined constructors for member default initialization only are considered not-the-best practice: https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#Rc-in-class-initializer
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For consistency reasons. But if you must initialize things like this, at least use the assignment syntax.
In this case, however, you could (and should) skip initialization completely, which will default-initialize the smart pointer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree, QScopedPointer
is initialized to Q_NULLPTR
by default. Fixed
13fe50e
to
b1e2158
Compare
Fixed 2 memory leaks in production code and a few in testcases. As a result leak_check_at_exit ASAN option does not need to turned off for non-gui tests. Smart pointers should be used elsewhere for consistency, but the sooner this fixes are delivered, the lesser memory leaks are introduced.
b1e2158
to
b204e8a
Compare
- Prevent database corruption when locked [#1219] - Fixes apply button not saving new entries [#1141] - Switch to Consolas font on Windows for password edit [#1229] - Multiple fixes to AppImage deployment [#1115, #1228] - Fixes multiple memory leaks [#1213] - Resize message close to 16x16 pixels [#1253]
- Prevent database corruption when locked [#1219] - Fixes apply button not saving new entries [#1141] - Switch to Consolas font on Windows for password edit [#1229] - Multiple fixes to AppImage deployment [#1115, #1228] - Fixes multiple memory leaks [#1213] - Resize message close to 16x16 pixels [#1253]
Fixed memory leaks non-gui tests
Description
Fixed 2 memory leaks in production code and a few in testcases. As a result
leak_check_at_exit
ASAN option does not need to turned off for non-gui tests.Smart pointers should be used elsewhere for consistency, but the sooner this fixes are delivered, the lesser memory leaks are introduced.
Motivation and context
Memory leaks are bugs in short, so motivation is pretty straightforward :)
How has this been tested?
No logic was altered, thus existing testcases are sufficient
Screenshots (if appropriate):
Types of changes
Checklist:
-DWITH_ASAN=ON
. [REQUIRED]