c++ - Opening database in invalid location causes memory leak -
i using qt 4.5.3 access sqlite database, :
class db : private boost::noncopyable { public: db( qstring file ) : filename( file ), realdb( null ), theconnectionestablished( false ) { } ~db() { if ( null != realdb.get() ) { realdb.reset( null ); } if ( theconnectionestablished ) { qsqldatabase::removedatabase( "connname" ); } } void open() { realdb.reset( new qsqldatabase( qsqldatabase::adddatabase( "qsqlite", "connname" ) ) ); theconnectionestablished = true; // open db realdb->setdatabasename( filename ); if ( ! realdb->open() ) { const qsqlerror dberror = realdb->lasterror(); const qstring errordesc = "error opening database : " + filename + "\ndatabase error : " + dberror.databasetext() + "\ndatabase driver error : " + dberror.drivertext(); // databaseerror class type accepts std::string logging purposes throw databaseerror( errordesc.tostdstring() ); } } const qstring filename; std::auto_ptr<qsqldatabase> realdb; bool theconnectionestablished; };
now if try test case (i using cxxtest) :
void test_failed_connection() { db obj( "/" ); ts_assert_throws( obj.open(), databaseerror ); }
i memory leak reported valgrind :
<error> <unique>0x5b</unique> <tid>1</tid> <kind>leak_definitelylost</kind> <what>986 (384 direct, 602 indirect) bytes in 1 blocks lost in loss record 23 of 23</what> <leakedbytes>986</leakedbytes> <leakedblocks>1</leakedblocks> <stack> <frame> <ip>0x4006d3e</ip> <obj>/opt/valgrind341/lib/valgrind/x86-linux/vgpreload_memcheck.so</obj> <fn>malloc</fn> <dir>/home/slawomir/valgrind-3.4.1/build/valgrind-3.4.1/coregrind/m_replacemalloc</dir> <file>vg_replace_malloc.c</file> <line>207</line> </frame> <frame> <ip>0x67fadc4</ip> <obj>/usr/lib/libsqlite3.so.0.8.6</obj> <fn>sqlite3_malloc</fn> </frame> <frame> <ip>0x67faf13</ip> <obj>/usr/lib/libsqlite3.so.0.8.6</obj> </frame> <frame> <ip>0x6816da3</ip> <obj>/usr/lib/libsqlite3.so.0.8.6</obj> </frame> <frame> <ip>0x68175fd</ip> <obj>/usr/lib/libsqlite3.so.0.8.6</obj> <fn>sqlite3_open16</fn> </frame> <frame> <ip>0x40ddef9</ip> <obj>/usr/lib/qt4/plugins/sqldrivers/libqsqlite.so</obj> </frame> <frame> <ip>0x7f34ae0</ip> <obj>/usr/lib/libqtsql.so.4.5.2</obj> <fn>qsqldatabase::open()</fn> </frame> </frame> </stack> </error>
does know how fix leak?
had browse through qt , sqlite sources ... interesting.
reading manual sqlite3_open16()
, http://www.sqlite.org/c3ref/open.html, 1 finds following quote:
whether or not error occurs when opened, resources associated database connection handle should released passing sqlite3_close() when no longer required.
qsqlitedriver::close()
seems calling that, http://qt.gitorious.org/qt/qt/blobs/4.7/src/sql/drivers/sqlite/qsql_sqlite.cpp, in case of open having been successful. sqlite's documentation might indicate sqlite3_close()
should called either case.
on other hand, http://www.sqlite.org/c3ref/close.html claims no-op if null
passed handle (which if open failed). sqlite sourcecode (diy - don't know web source browser interface it) confirms that, returns if called null
.
well - nitty-gritty fun of issue...
naively, 1 assumes failure of sqlite3_open*()
imply null
db handle. according sqlite's sources, read opendatabase()
in main.c
, that's not true - call can fail still return non-null
db handle.
qt looks assumes failure open db connection implies receiving null
db handle. that's not sqlite does. documentation clearer, though.
try adding close qsqlitedriver::open()
, see if fixes leak. if so, file bug qt guys, , 1 sqlite folks have documentation clarified ;-)
Comments
Post a Comment