I have isolated a problem with Visual C++ .NET 2003 and exception handling. In some cases, when the code is compiled in release (!), when an exception is thrown, the call stack unwinding is incorrect. This may result by a crash or memory corruption. Note : "alloca" is used in the code, but it is not executed. I have a simple example to demonstrate the problem.
Is there a fix available for this
--------------
Note: the problem occurs because the compiler generates something like:
void CTestClass::someFuncWithCorruption(const char* sSomeData)
{
00401020 push ebp
00401021 lea ebp,[esp-74h]
// then, place the exception handler on the stack
if "mov ebp, esp" was used, everything would be fine
-------------
The following code demonstrated the problem
------------------------------------------------------------------------------------------------
#include "malloc.h"
#include "stdio.h"
#include "stdarg.h"
#include <iostream>
using namespace std;
// An exception class
class CMyException
{
public:
};
// A class with a constructor and destructor that we place on the stack
class CClassOnTheStack
{
public:
CClassOnTheStack(){
m_savedThis=this;
}
~CClassOnTheStack(){
if (m_savedThis!=this) {
// __asm {int 3}; // can be useful for debug purposes
cout<<"~CSomeClass : corrupted\n";
}
}
private:
CClassOnTheStack* m_savedThis;
};
//! Just do nothing
char* DoNothing(const char* sInput, char* sBuffer)
{
return (char*)sInput;
}
// A test class. This is not necessary
class CTestClass
{
public:
void someFuncWithCorruption(const char* sSomeData);
void someFunc(const char* sSomeData);
};
//! This will throw an exception. During the frame unwind,
//! ~CClassOnTheStack is called with a corrupted this
void CTestClass::someFuncWithCorruption(const char* sSomeData)
{
CClassOnTheStack MyClass1;
if (sSomeData==NULL)
throw CMyException();
else
// Note: alloca is not called in the test (we use sSomeData=NULL)
DoNothing(sSomeData, (char*)alloca(10));
std::string s1,s2,s3,s4,s5;
}
//! This will throw an exception. It works fine
void CTestClass::someFunc(const char* sSomeData)
{
CClassOnTheStack MyClass1;
if (sSomeData==NULL)
throw CMyException();
else
// Note: alloca is not called in the test (we use sSomeData=NULL)
DoNothing(sSomeData, (char*)alloca(10));
std::string s1,s2,s3,s4;
}
// Try the 2 functions. One works, one may corrupt the memory
int main()
{
cout << "start test\n";
CTestClass* pTest=new CTestClass(); // Use a pointer to prevent inline optimization
try{
pTest->someFunc(NULL);
} catch(...) {
cout << "Exception in someFunc\n";
}
try{
pTest->someFuncWithCorruption(NULL);
} catch(...) {
cout << "Exception in someFuncWithCorruption \n";
}
delete pTest;
cout << "test stopped normally. Press <enter>\n";
char c=getchar();
return 0;
}

VS 2003, C++: exception unwind => destructor called, "this" is wrong (=> corruption)
kcvaio
The existence of alloca changes the way registers track stack variables, so I can see it being a factor in a possible VC7.1 (VS2003) bug.
I can only test your code under VC8 (VS2005), and it runs okay under Release.
Perhaps someone using VC7.1 can give this a try.
Brian