Identifying cause of deleting released memory

I have a particular class hierarchy that is causing memory to be released twice.

What seems to be the problem is the following section of code:
1
2
3
4
5
void FOO::ProcessTable (const TABLE & table)
{   SQLERR		sqlerr;
    const KEYDEF *      prikey; 
    string		temp;
    TABLEDEF		tabledef (table);


An exception is getting thrown several levels deep in TABLEDEF's construction.
I know why the exception is being thrown and how to fix it. That's not the issue. The problem is that the exception handling is unwinding objects on the stack and calling TABLEDEF's destructor, which in turn calls every other destructor in the heirarchy all the way to std::string which is the base class. string's destructor is calling delete which is causing an abend attempting to release memory that is not allocated. I know the underlying string was in fact allocated and correct.

Before I fix the cause of the exception being thrown, I want to find why string memory is apparently getting released twice. I've checked all the constructors in the chain and all are passing objects as const reference to the next level. All the destructors are virtual.

Any suggestions on how to find the cause of the memory being released twice?
I've tried various stratagies in the debugger to no avail, including setting a memory access breakpoint on the underlying string object. Stepping into the throw was no help.

Note: The try/catch logic is one level up from this function.
Last edited on
... std::string which is the base class.


What does this hierarchy look like, pseudo-code wise? Is the inheritance of each base class virtual all the way down the line?
1
2
3
4
5
6
TABLEDEF::TABLEDEF (const TABLE & tbl) : TABLE (table)
TABLE::TABLE (const SQLOBJ & sqlobj) : SQLOBJ(sqlobj)
SQLOBJ::SQLOBJ (const ENSCRIBE & esc) : ENSCRIBE(esc)
ENSCRIBE::ENSCRIBE (const gFILE & gf) : gFILE(gf)
gFILE::gFILE (const FNAME & fn) : FNAME (fn)
FNAME::FNAME (const string & str) : string(str) 


Yes, it's virtual all the way down.

Last edited on
Sorry about the latency between my posts but I suspect that you already know what we need next. Is a stack dump a valid option here?

Logically speaking, if the std::string is being deleted twice then then that is because the destructor is being called twice. You're not the type of guy to miss a scoping issue so we're up to considering the fringe cases. Is there anything unique about the platform? I'm a Windows guy here :/.
Last edited on
I've looked at the stack dump. Stack dump is in deallocate called from the string destructor. Destructors in reverse order on the stack all the way back to where TABLEDEF was instantiated (line 5 in first post). Absolutely nothing enlightening there. All the destructors are trivial. No dynamic memory allocations or deletions.

Yeah, the platform is unique. It's a C++03 implementation (latest available). But I don't see that as an issue.

I'm leaning towards thinking it has something to do with how the stack is unwound i.e. the locals are destructed as if the function was being exited before control is passed to the catch handler in the function one level up. I've tried stepping into the throw statement, but that calls library code that does not have symbols available.

I've tried setting a memory write breakpoint on string's internal pointer. I can see it get overwritten, but I haven't been able to catch where it's occurring. i.e. It seems to be occurring in protected library code which I can't step into. By the time control returns to non-protected code, the damage has been done and I can't tell from where.




I'm starting to think TABLEDEF's destructor is getting called twice. That would fit the symptoms I'm seeing. The destructor for TABLEDEF and all of its base classes except std::string are trivial, so there is no harm in them being called twice. Of course, std::string's destructor is not trivial and can not be called twice.

The only thing that would cause TABLEDEF's destructor to be called twice is a problem in handling the unwind stack as variables are destructed as a result of exiting ProcessTable and invoking the enclosing catch handler.

I'm going to try setting a breakpoint on TABLEDEF's destructor and see if I can confirm it is getting called twice. If it is, I don't hold out much hope for determining why, since that is in a system code library.
Here's something you can do:
1. Identify the place where the string gets assigned last.
2. Identify the function that destroys the string's internal buffer.
3. Put a breakpoint at location #1, run until hit, and take note of the address of the string's internal buffer.
4. Before resuming execution, put a conditional breakpoint at location #2, the condition being that the address of the pointer must equal the value from #3.
5. Continue execution.
A memory that is released twice usually hints at a wrongful [shallow] copy
Topic archived. No new replies allowed.