RE: Stack frame incorrect on stack unwinding during exception
By the way, I did notice that when I enter Exception::raiseException() there
is no stack frame setup (e.g. no push ebp, move ebp, esp). Not sure if this
has anything to do with the problem.
--
Thanks,
Nick
"nickdu" wrote:
I'm tracking down a problem where we're running into an access violation
while unwinding the stack after throwing a C++ exception. From my
investigation it appears the stack frame is not correctly setup. Below is an
example of what I've observed.
When I enter my function Validate() (shown below) esp = 0x4d6f62c and ebp =
0x4d6fbf4. Then it does:
push ebp
lea bp, [esp - 0x894]
At which point esp = 0x4d6f628 and ebp = 0x4d6ed94. So the stack frame for
Validate's locals should be ebp = 0x4d6ed94. And in fact [ebp + 0x830] is
the 'this' pointer for Validate's STL string 'x' (when ebp = 0x4d6ed94).
However, when I throw an exception in Validate() it ends up in a little piece
of thunk code shown below:
lea ecx, [ebp + 0x830]
jmp std::basic_string::~basic_string()
The offset from ebp is correct, but the value of ebp is 0x4d6f628 which is
not correct. What happened? I did notice that this it the value of esp
after the locals were accounted for in Validate().
Snippets of code:
===========
#define T_OLEDB_ERR_DEADLY_STR(STR) do { Exception::raiseException(false,
STR, __FILE__, __LINE__); } while(0)
class TException
{
public:
TException(const char *, int iExceptionCode = 0, DWORD dwIP = 0);
TException(const char * pszMessage, const char * pszFileName, int
iLineNumber, const char * pszHostName, int iExceptionCode = 0);
virtual ~TException();
const char * GetMessage();
const char * GetFileName();
const char * GetHostName();
const int GetLineNumber();
const int GetExecptionCode();
const DWORD GetInstructionPointer();
static void InstallSEHandler(LPCTSTR sDir = NULL);
private:
static TCHAR s_sDir[MAX_PATH];
static void translate_SE(unsigned int u, _EXCEPTION_POINTERS* pExp);
CStdString m_strMessage;
CStdString m_strFileName;
int m_iLineNumber;
CStdString m_strHostName;
int m_iExceptionCode;
DWORD m_dwIP;
};
class Exception : public TException
{
public:
Exception(HRESULT hr, bool bRetryable, const char * pszMessage, const char
* pszFileName, int iLineNumber, const char * pszHostName) :
TException(pszMessage, pszFileName, iLineNumber, pszHostName), m_hr(hr),
m_bRetryable(bRetryable)
{
}
void SetDBInfo(HRESULT hr, CComPtr<IUnknown> &m_spUnk);
static void raiseException(bool bRetryAble, const char*pszMessage, const
char *pszFileName, int iLineNumber, HRESULT hr, CComPtr<IUnknown> m_spUnk,
CComPtr<IUnknown> pFI, CDynamicAccessor &acc);
static void raiseException(bool bRetryAble, const char*pszMessage, const
char *pszFileName, int iLineNumber, HRESULT hr, IUnknown* m_spUnk, IUnknown*
pFI);
static void raiseException(bool bRetryAble, const char*pszMessage, const
char *pszFileName, int iLineNumber, HRESULT hr, CComPtr<IUnknown> m_spUnk);
static void raiseException(bool bRetryAble, const char*pszMessage, const
char *pszFileName, int iLineNumber, HRESULT hr);
static void raiseException(bool bRetryAble, const char*pszMessage, const
char *pszFileName, int iLineNumber);
HRESULT GetHR() { return m_hr; }
bool GetRetry() { return m_bRetryable; }
private:
HRESULT m_hr;
bool m_bRetryable;
};
void Validate()
{
std::string x;
.
.
.
if (x.length != 0)
T_OLEDB_ERR_DEADLY_STR(x.c_str());
}
--
Thanks,
Nick