On 10-10-30 10:22 PM, Sohail Somani wrote:
After fixing this, another leak remains. I've attached both the patch
and the modified test code with the valgrind trace.
Well I think I know where the leak is coming from. Here we use the save
implementation from the session:
session()->implSave(*this); // ptr_impl.h:45
At this point, the this (MetaDbo<C>) object has a reference count of 1
because it is held in the dirtyObjects_ variable.
In the implSave function:
// Session_impl.h:180
transaction_->objects_.push_back(new ptr<C>(&dbo));
In this call, the ptr<C> constructor increments the reference count. So
now the reference count is 2.
Then if exceptions happen when committing the transaction, the reference
count is never decremented. Instant memory leak.
I would recommend going through all the places where a decRef is
required at the end of scope and replacing the imperative statements
with a scope guard.
Anyway, I've attached a patch and tests that fix all the leaks in my
model tests, according to valgrind.
I guess I have to stop telling people that memory leaks in C++ are a
thing of the past!
Keep up the good work, love dbo.
--
Sohail Somani
--
iBlog : http://uint32t.blogspot.com
iTweet: http://twitter.com/somanisoftware
iCode : http://bitbucket.org/cheez
diff -r 042b12c62486 -r a49c42291b87 vendor/Wt/Wt/Dbo/Session.C
--- a/vendor/Wt/Wt/Dbo/Session.C Sat Oct 30 15:53:13 2010 -0700
+++ b/vendor/Wt/Wt/Dbo/Session.C Sat Oct 30 22:52:02 2010 -0700
@@ -152,7 +152,15 @@
MetaDboBaseSet::iterator i = dirtyObjects_.begin();
MetaDboBase *dbo = *i;
dirtyObjects_.erase(i);
- dbo->flush();
+ try
+ {
+ dbo->flush();
+ }
+ catch(...)
+ {
+ dbo->decRef();
+ throw;
+ }
dbo->decRef();
}
}
diff -r 042b12c62486 -r a49c42291b87 vendor/Wt/Wt/Dbo/Session_impl.h
--- a/vendor/Wt/Wt/Dbo/Session_impl.h Sat Oct 30 15:53:13 2010 -0700
+++ b/vendor/Wt/Wt/Dbo/Session_impl.h Sat Oct 30 22:52:02 2010 -0700
@@ -22,6 +22,10 @@
ClassMapping<C> *mapping = new ClassMapping<C>();
mapping->tableName = tableName;
+ ClassRegistry::iterator i = classRegistry_.find(&typeid(C));
+ if(i != classRegistry_.end())
+ delete i->second;
+
classRegistry_[&typeid(C)] = mapping;
tableRegistry_[tableName] = mapping;
}
diff -r 042b12c62486 -r a49c42291b87 vendor/Wt/Wt/Dbo/Transaction.C
--- a/vendor/Wt/Wt/Dbo/Transaction.C Sat Oct 30 15:53:13 2010 -0700
+++ b/vendor/Wt/Wt/Dbo/Transaction.C Sat Oct 30 22:52:02 2010 -0700
@@ -45,13 +45,13 @@
bool Transaction::commit()
{
if (isActive()) {
- committed_ = true;
if (impl_->transactionCount_ == 1) {
impl_->commit();
-
+ committed_ = true;
return true;
} else
+ committed_ = true;
return false;
} else
return false;
struct Class
{
Class():integer(5){}
int integer;
template<typename Action>
void
persist(Action & a)
{
dbo::field(a,integer,"integer");
}
};
KIMI_UNIT_TEST( TestWtMapClassMemoryLeak )
{
dbo::backend::Sqlite3 connection(":memory:");
dbo::Session session;
session.setConnection(connection);
session.mapClass<Class>("class");
session.mapClass<Class>("class"); // This used to leak because the old
mapping was overwritten
}
KIMI_UNIT_TEST( TestWtFlushLeak )
{
dbo::backend::Sqlite3 connection(":memory:");
dbo::Session session;
session.setConnection(connection);
session.mapClass<Class>("class");
Wt::Dbo::Transaction t(session);
session.add(new Class);
BOOST_REQUIRE_THROW(t.commit(),std::runtime_error); // This used to leak
because an exception was thrown
}
------------------------------------------------------------------------------
Nokia and AT&T present the 2010 Calling All Innovators-North America contest
Create new apps & games for the Nokia N8 for consumers in U.S. and Canada
$10 million total in prizes - $4M cash, 500 devices, nearly $6M in marketing
Develop with Nokia Qt SDK, Web Runtime, or Java and Publish to Ovi Store
http://p.sf.net/sfu/nokia-dev2dev
_______________________________________________
witty-interest mailing list
witty-interest@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/witty-interest