关于CLR调用VC++ DLL, 抛出Exception没有stack unwinding
先说一下stack unwinding的概念: 函数调用返回时, 会恢复函数进入前外层部分的参数, 并销毁退出的函数的参数和临时变量被称为stack unwinding. 在try模块中抛出异常后, 一样会进行stack unwinding. 那些在try语句块中的变量的析构函数会被逆顺序调用. 看一个例子:
#include <iostream>
using namespace std;
class A {
public:
A() { cout << "A ctor" << endl; }
~A() { cout << "A dtor" << endl; }
};
class B {
public:
B() { cout << "B ctor" << endl; }
~B() { cout << "B dtor" << endl; }
};
int _tmain(int argc, _TCHAR* argv[]) {
try {
A a;
B b;
throw("new exception");
} catch(const char *ex) {
cout << ex << endl;
}
getchar();
return 0;
}
在抛出"new exception"异常后, 类型A和类型B的析构函数被逆向顺序调用. --> stack unwinding. 那么如果不幸的是在某个类型的析构函数里抛出一个exception那又如何挽救呢? 假设B类型在析构时抛出了异常, 导致A类型无法正常析构, 看一个例子:
#include <iostream>
using namespace std;
class A {
public:
A() { cout << "A ctor" << endl; }
~A() { cout << "A dtor" << endl; }
};
class B {
public:
B() { cout << "B ctor" << endl; }
~B() {
cout << "B dtor" << endl;
throw("B dtor exception");
}
};
int _tmain(int argc, _TCHAR* argv[]) {
try {
A a;
B b;
throw("new exception");
} catch(const char *ex) {
cout << ex << endl;
}
getchar();
return 0;
}
A类型无法正常析构. 没有其它办法再进行控制了. C++运行时会调用terminate来进行处理.通过set_terminate设置自定义处理函数可以提供开发人员自己的处理行为.
#include <iostream>
using namespace std;
void CustomTerminate(void) {
cout << "terminate" << endl;
}
class A {
public:
A() { cout << "A ctor" << endl; }
~A() { cout << "A dtor" << endl; }
};
class B {
public:
B() { cout << "B ctor" << endl; }
~B() {
cout << "B dtor" << endl;
throw("B dtor exception");
}
};
int _tmain(int argc, _TCHAR* argv[]) {
set_terminate(CustomTerminate);
try {
A a;
B b;
throw("new exception");
} catch(const char *ex) {
cout << ex << endl;
}
getchar();
return 0;
}
现在有这么一个情况, 当C++/CLI程序调用VC++的DLL, 该DLL内部抛出异常. 而在C++/CLI程序部分由try/catch捕捉. 但却没有引发 stack unwinding. 感兴趣的同学也可以自己试一试, 确实存在这个问题.
然后在网络上搜索了一下, 在Visual Studio的feedback里有一位叫potrto的人提出了同样的问题. Visual Studio Team给出的resolution是: Thanks for reporting this issue. We have identified the root cause and fixed this issue for the next release of CLR. 等于暂时没有解决= =.
#include <iostream>
using namespace std;
class A {
public:
A() { cout << "A ctor" << endl; }
~A() { cout << "A dtor" << endl; }
};
class B {
public:
B() { cout << "B ctor" << endl; }
~B() { cout << "B dtor" << endl; }
};
int _tmain(int argc, _TCHAR* argv[]) {
try {
A a;
B b;
throw("new exception");
} catch(const char *ex) {
cout << ex << endl;
}
getchar();
return 0;
}
在抛出"new exception"异常后, 类型A和类型B的析构函数被逆向顺序调用. --> stack unwinding. 那么如果不幸的是在某个类型的析构函数里抛出一个exception那又如何挽救呢? 假设B类型在析构时抛出了异常, 导致A类型无法正常析构, 看一个例子:
#include <iostream>
using namespace std;
class A {
public:
A() { cout << "A ctor" << endl; }
~A() { cout << "A dtor" << endl; }
};
class B {
public:
B() { cout << "B ctor" << endl; }
~B() {
cout << "B dtor" << endl;
throw("B dtor exception");
}
};
int _tmain(int argc, _TCHAR* argv[]) {
try {
A a;
B b;
throw("new exception");
} catch(const char *ex) {
cout << ex << endl;
}
getchar();
return 0;
}
A类型无法正常析构. 没有其它办法再进行控制了. C++运行时会调用terminate来进行处理.通过set_terminate设置自定义处理函数可以提供开发人员自己的处理行为.
#include <iostream>
using namespace std;
void CustomTerminate(void) {
cout << "terminate" << endl;
}
class A {
public:
A() { cout << "A ctor" << endl; }
~A() { cout << "A dtor" << endl; }
};
class B {
public:
B() { cout << "B ctor" << endl; }
~B() {
cout << "B dtor" << endl;
throw("B dtor exception");
}
};
int _tmain(int argc, _TCHAR* argv[]) {
set_terminate(CustomTerminate);
try {
A a;
B b;
throw("new exception");
} catch(const char *ex) {
cout << ex << endl;
}
getchar();
return 0;
}
现在有这么一个情况, 当C++/CLI程序调用VC++的DLL, 该DLL内部抛出异常. 而在C++/CLI程序部分由try/catch捕捉. 但却没有引发 stack unwinding. 感兴趣的同学也可以自己试一试, 确实存在这个问题.
然后在网络上搜索了一下, 在Visual Studio的feedback里有一位叫potrto的人提出了同样的问题. Visual Studio Team给出的resolution是: Thanks for reporting this issue. We have identified the root cause and fixed this issue for the next release of CLR. 等于暂时没有解决= =.