Is there a potential for resource leak/double free here?
Posted
by
nhed
on Stack Overflow
See other posts from Stack Overflow
or by nhed
Published on 2011-03-20T19:06:30Z
Indexed on
2011/03/20
19:19 UTC
Read the original article
Hit count: 218
c++
|memory-leaks
The following sample (not compiled so I won't vouch for syntax) pulls two resources from resource pools (not allocated with new
), then "binds" them together with MyClass for the duration of a certain transaction.
The transaction, implemented here by myFunc
, attempts to protect against leakage of these resources by tracking their "ownership". The local resource pointers are cleared when its obvious that instantiation of MyClass
was successful. The local catch
, as well as the destructor ~MyClass
return the resources to their pool (double-frees are protected by teh above mentioned clearing of the local pointers).
Instantiation of MyClass can fail and result in an exception at two steps (1) actual memory allocation, or (2) at the constructor body itself. I do not have a problem with #1, but in the case of #2, if the exception is thrown AFTER m_resA
& m_resB
were set. Causing both the ~MyClass
and the cleanup code of myFunc
to assume responsibility for returning these resources to their pools.
Is this a reasonable concern?
Options I have considered, but didn't like:
- Smart pointers (like boost's shared_ptr). I didn't see how to apply to a resource pool (aside for wrapping in yet another instance).
- Allowing double-free to occur at this level but protecting at the resource pools.
- Trying to use the exception type - trying to deduce that if
bad_alloc
was caught that MyClass did not take ownership. This will require a try-catch in the constructor to make sure that any allocation failures inABC() ...more code here...
wont be confused with failures to allocate MyClass.
Is there a clean, simple solution that I have overlooked?
class SomeExtResourceA;
class SomeExtResourceB;
class MyClass {
private:
// These resources come out of a resource pool not allocated with "new" for each use by MyClass
SomeResourceA* m_resA;
SomeResourceB* m_resB;
public:
MyClass(SomeResourceA* resA, SomeResourceB* resB):
m_resA(resA), m_resB(resB)
{
ABC(); // ... more code here, could throw exceptions
}
~MyClass(){
if(m_resA){
m_resA->Release();
}
if(m_resB){
m_resB->Release();
}
}
};
void myFunc(void)
{
SomeResourceA* resA = NULL;
SomeResourceB* resB = NULL;
MyClass* pMyInst = NULL;
try {
resA = g_pPoolA->Allocate();
resB = g_pPoolB->Allocate();
pMyInst = new MyClass(resA,resB);
resA=NULL; // ''ownership succesfully transfered to pMyInst
resB=NULL; // ''ownership succesfully transfered to pMyInst
// Do some work with pMyInst;
...;
delete pMyInst;
} catch (...) {
// cleanup
// need to check if resA, or resB were allocated prior
// to construction of pMyInst.
if(resA) resA->Release();
if(resB) resB->Release();
delete pMyInst;
throw; // rethrow caught exception
}
}
© Stack Overflow or respective owner