C++ delete throwing exception

J

John Fullman

I have an application with a class that just doesn't seem to like
destroying...

I have a member that is stored on the heap and it is deleted in the
destructor.

When I run the app in debug mode, I break at the destructor and the
member is still active on the heap. When I step through the delete, it
throws an exception saying that there's nothin' to delete. Wierd.

If it's worth anything, the class in question is imported from another
DLL using __declspec(import) and is cannonical (ie. has a default
constructor, copy constructor, = operator, and destructor)

Has anyone seen this behavior before or am I just doing something wierd
in my code somewhere that I don't see???
 
J

Jim Langston

John Fullman said:
I have an application with a class that just doesn't seem to like
destroying...

I have a member that is stored on the heap and it is deleted in the
destructor.

When I run the app in debug mode, I break at the destructor and the
member is still active on the heap. When I step through the delete, it
throws an exception saying that there's nothin' to delete. Wierd.

If it's worth anything, the class in question is imported from another
DLL using __declspec(import) and is cannonical (ie. has a default
constructor, copy constructor, = operator, and destructor)

Has anyone seen this behavior before or am I just doing something wierd
in my code somewhere that I don't see???

Hard to say without seeing the class.
 
J

John Fullman

class dllobject_mb RuleItem
{
public:
RuleItem();
RuleItem(Event* ev);
RuleItem(NonTerminal* nt);
RuleItem(Token* t);

RuleItem(const RuleItem& copy);
RuleItem& operator=(const RuleItem& copy);
~RuleItem();

NonTerminal* NonTerminalRef;
Token* TokenRef;
Event* EventRef;

bool IsToken();
bool IsEvent();
bool IsNonTerminal();

JFC::String ToString();
bool operator==(const RuleItem& operand) const;
bool operator>(const RuleItem& operand) const;
};
}}


//Destructor Code:
RuleItem::~RuleItem()
{
if(EventRef != 0)
delete EventRef;
EventRef = 0;
if(TokenRef != 0)
delete TokenRef;
TokenRef = 0;
NonTerminalRef = 0;
}


My members are public, but I tested the scenario with this code:
RuleItem* tok = new RuleItem(new Token(0, "fdsf"));
delete tok;
and that kills it somehow. The constructors do only what you'd expect.
 
J

John Harrison

John said:
class dllobject_mb RuleItem
{
public:
RuleItem();
RuleItem(Event* ev);
RuleItem(NonTerminal* nt);
RuleItem(Token* t);

RuleItem(const RuleItem& copy);
RuleItem& operator=(const RuleItem& copy);
~RuleItem();

NonTerminal* NonTerminalRef;
Token* TokenRef;
Event* EventRef;

bool IsToken();
bool IsEvent();
bool IsNonTerminal();

JFC::String ToString();
bool operator==(const RuleItem& operand) const;
bool operator>(const RuleItem& operand) const;
};
}}


//Destructor Code:
RuleItem::~RuleItem()
{
if(EventRef != 0)
delete EventRef;
EventRef = 0;
if(TokenRef != 0)
delete TokenRef;
TokenRef = 0;
NonTerminalRef = 0;
}

This can be simplified, it's OK to delete 0, and obviously the values of
your memory variable don't matter after the destructor has exitted.

RuleItem::~RuleItem()
{
delete EventRef;
delete TokenRef;
}
My members are public, but I tested the scenario with this code:
RuleItem* tok = new RuleItem(new Token(0, "fdsf"));
delete tok;
and that kills it somehow. The constructors do only what you'd expect.

Well the only thing missing is the constructor code. Possibly the error
is in there. As Jim says it's hard to fix coding errors without seeing
the code.

You mentioned DLLs, you do realise that it is not possible to allocate
memory in a DLL and then free it in the main program (or another DLL).
In other words each DLL has it's own heap, and you can't mix them up. I
think that would be the first place to look.

john
 
J

John Fullman

Thanks John! That is my problem exactly!

I am newing mem in the main app and deleting from the dll.
This is a design flaw that I didn't account for in multiple locations.

This does, however, draw out another problem....

I have a dll-imported class with a templated array member. This means,
when I call the LinkedList<Token>::Add() function from application
space, it is newed in application space. Then, it is destroyed in dll
space, because it belongs to a dll imported class. The solution seems
to be that I need to cause the templated collection to be pre-compiled
in dll space.
If I do the following in my dll:

class TokenList : public LinkedList<Token>
{
};

and use the TokenList as the member, will that fix the problem?

Thanks.
 
J

John Harrison

John said:
Thanks John! That is my problem exactly!

I am newing mem in the main app and deleting from the dll.
This is a design flaw that I didn't account for in multiple locations.

This does, however, draw out another problem....

I have a dll-imported class with a templated array member. This means,
when I call the LinkedList<Token>::Add() function from application
space, it is newed in application space. Then, it is destroyed in dll
space, because it belongs to a dll imported class. The solution seems
to be that I need to cause the templated collection to be pre-compiled
in dll space.
If I do the following in my dll:

class TokenList : public LinkedList<Token>
{
};

and use the TokenList as the member, will that fix the problem?

Thanks.

This is getting a bit beyond my expertise. I know about the DLL memory
allocation problem but not in detail how to fix it or work around it.
Best bet is to try a microsoft group, perhaps

john
 
O

Old Wolf

John said:
You mentioned DLLs, you do realise that it is not possible to
allocate memory in a DLL and then free it in the main program
(or another DLL). In other words each DLL has it's own heap,
and you can't mix them up. I think that would be the first place
to look.

I believe you can mix them up as long as you ensure they are both
using the same C runtime library (which wouldn't happen if one were
built in release mode and one in debug mode, for example), because
once a DLL is loaded, it just becomes part of the current process.
 
S

Shezan Baig

John said:
Thanks John! That is my problem exactly!

I am newing mem in the main app and deleting from the dll.
This is a design flaw that I didn't account for in multiple locations.

This does, however, draw out another problem....

I have a dll-imported class with a templated array member. This means,
when I call the LinkedList<Token>::Add() function from application
space, it is newed in application space. Then, it is destroyed in dll
space, because it belongs to a dll imported class. The solution seems
to be that I need to cause the templated collection to be pre-compiled
in dll space.


You could try using an allocator as an extra level of indirection,
instead of using global 'new' and 'delete' directly. (This is also
considered a good practice, to allow clients to pass in any allocator
they want.)

Hope this helps,
-shez-
 
J

John Fullman

Well all my components are compiled in Dubug mode and I have certainly
found this mixing up heaps deal to be the problem.

I am not sure if I want to go as far as to write an allocator class...
as a last resort, maybe... Too many layers of abstraction scare me :p
 
J

John Fullman

Hey all... well I found a viable solution to the problem and it looks
like I was on the right track with the inheritance thing:

class __declspec(import) TokenList : public LinkedList<Token> {};

As long as I make sure the class gets exported, it forces all the
members of the template to be compiled into the dll.. and walla!!..
everything is allocated in dll-space...

Thanks to everyone who contributed.... You guys have been really
helpful :)
I'll be sure to jump back to this forum whenever I get a chance and
help you guys out once in a while :)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,024
Latest member
ARDU_PROgrammER

Latest Threads

Top