Sign in to follow this  
Dan_

Exceptional problem

Recommended Posts

Dan_    139
I've created a few exception classes for error handling in my application, but I have come across quite an odd problem. My main exception class has the following definition:
class Exception
{
private:
	wstring m_Function;
	wstring m_Message;

public:
	Exception(const wstring &function, const wstring &message);
	Exception(const Exception &ex);
	virtual ~Exception();

	const wstring &getFunction()const;
	const wstring &getMessage()const;
};

In my code when a problem arises I do the following:
throw Exception(L"Function", L"Message");

And I catch it using:
catch (Exception ex)
{
    /* ... */
}

But by the time it reaches the catch block, the member m_Function appears as <bad_ptr> in the Visual Studio debugger. The second parameter appears normal as "Message" in the debugger though. When the code leaves the catch block and the Exception instance is destructed the debugger breaks at _Container_base::_Orphan_all() which I assume is for the m_Function wstring. I have this class and some others in a static library and in my application is used in both a DLL and a main executable and use the same library with the same headers compiled and linked with both the DLL and the exe. The exception where this is happening is thrown in the DLL and is caught in the exe. I have no idea why this is happening.

Share this post


Link to post
Share on other sites
rip-off    10979
Quote:

The exception where this is happening is thrown in the DLL and is caught in the exe.


The source of the problem. I'm pretty sure its a bad idea to do that. Typically this is because your compiler will use the Exception classes copy constructor and destructor and will end up with some funky problems because DLLs and exes do not share the same heap.

AFAIK the general rule is not to pass non POD types across dll boundaries. This unfortunately includes the useful std::containers, including std::string. I have only written 1 DLL, but it exposed only a C interface(mainly createObject() and destroyObject() free functions), with the addition of returning a pointer to a pure virtual class interface (which I gather is ok). Then I used a bunch of inline functions in the DLL's header to provide a nice interface, something like this:

class DLLclass
{
public:
virtual ~DLLclass(){}

void someFunctionTakingAString( const std::string &str )
{
someFunctionTakingAString(str.c_str(),str.length());
}
void someFunctionThatMightThrow()
{
int res = private_someFunctionThatMightThrow();
if( res < 0 )
{
throw someInlinedSimpleExceptionType();
}
}

static boost::shared_ptr<DLLclass> dllClassFactory(/*ctor params*/)
{
DLLclass *instance = private_dllClassFactory();
if( instance )
{
return boost::shared_ptr<DLLclass>(instance,&destroy);
}
else
{
throw constructorExceptionClass();
}
}
private:
// implemented inside DLL
virtual void someFunctionTakingAString( const char *, int len ) = 0;
// returns < 0 to signal an error
virtual int private_someFunctionThatMightThrow() = 0;

// returns 0 on errors
static MY_DLL_API DLLclass *private_dllClassFactory();
static MY_DLL_API destroy( DLLclass * );
};






Because the exception throwing and std::container using functions are compiled into the exe, at no stage does a complex type have to cross the DLL boundary.

I didn't actually end up making any member functions that would throw (the only one that could throw were the constructors IIRC). But that was the way I decided I would do it if I had to make such a function. The absence of exceptions simplified the interface to translation functions for std::strings and std::vectors.

It was ugly TBH, I'd really like to know if there is a better way of doing this.

Share this post


Link to post
Share on other sites
Dan_    139
Thanks for the reply. I've gone ahead and changed my application so that no exceptions are passed from the DLL to the exectuable. I've instead caught the exceptions in the code in my DLL and I then give a certain return value to indicate failure for that particular function. Although I am still getting the same crash when it attempts to destruct the Exception class. I am not doing anything funky at all in the exception code. Here's the code for my Exception class:


Exception::Exception(const wstring &function, const wstring &message)
{
m_Function = function;
m_Message = message;
}

Exception::Exception(const Exception &ex)
{
m_Function = ex.m_Function;
m_Message = ex.m_Message;
}

Exception::~Exception()
{
}

const wstring &Exception::getFunction()const
{
return m_Function;
}

const wstring &Exception::getMessage()const
{
return m_Message;
}



Are there any specific compiler/linker settings for Visual Studio 2005 that could cause this kind of problem?

Share this post


Link to post
Share on other sites
Celvin    122
Quote:

[...] because DLLs and exes do not share the same heap

Says who? Guess you meant to say the heap management structures could be different, depending on what toolchain / language you used to create the DLL (could be a different one as the one used to develop the application), which could corrupt objects on the heap.

But in general, unless specified otherwise (HeapCreate() etc.), a DLL shares it's application's heap.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this