Closed
Description
The sqlite::database constructor has a potential memory leak if opening the database fails for whatever reason:
database(std::u16string const & db_name): _db(nullptr) {
sqlite3* tmp = nullptr;
auto ret = sqlite3_open16(db_name.data(), &tmp);
if(ret != SQLITE_OK) exceptions::throw_sqlite_error(ret);
_db = std::shared_ptr<sqlite3>(tmp, [=](sqlite3* ptr) { sqlite3_close_v2(ptr); }); // this will close the connection eventually when no longer needed.
//_db.reset(tmp, sqlite3_close); // alternative close. (faster?)
}
accordingly to https://www.sqlite.org/c3ref/close.html one must close the handle even if open returned an error. The above can be fixed by moving the fail check and the exception throwing after defining the _db shared_ptr, so it will call sqlite3_close_v2 at stack unwinding. One can prefer to do an explicit close instead, which is cheaper but more verbose. I took the 1st approach, below:
database(std::u16string const & db_name): _db(nullptr) {
sqlite3* tmp = nullptr;
auto ret = sqlite3_open16(db_name.data(), &tmp);
_db = std::shared_ptr<sqlite3>(tmp, [=](sqlite3* ptr) { sqlite3_close_v2(ptr); }); // this will close the connection eventually when no longer needed.
if(ret != SQLITE_OK) exceptions::throw_sqlite_error(ret);
//_db.reset(tmp, sqlite3_close); // alternative close. (faster?)
}
Metadata
Metadata
Assignees
Labels
No labels