RaiseFailFastException函数
引发绕过所有异常处理程序(基于帧或矢量)的异常。引发此异常将终止应用程序并调用Windows错误报告(如果Windows错误报告正在运行)。
原型:
VOID WINAPI RaiseFailFastException( __in_opt PEXCEPTION_RECORD pExceptionRecord, __in_opt PCONTEXT pContextRecord, __in DWORD dwFlags );
_purecall函数
默认纯虚拟函数调用错误处理程序。 当调用纯虚拟成员函数时,编译器生成调用此函数的代码。
原型:
extern "C" int __cdecl _purecall();
深入解析pure virtual function call
在本文中,我们将不解释为什么会提示“纯虚拟函数调用”和如何提示“纯虚拟函数调用”,而是详细解释在win32平台的构造函数/析构函数中直接/间接调用纯虚拟函数时程序本身。在开始时,将显示一个经典示例,在这个示例中,它将提示一个带有“纯虚拟函数调用”的消息框。
/** * "pure virtual function call" on win32 platform * filename: testWin32PVFC.cpp */ #include <iostream> #define PI 3.1415926 using namespace std; class Shape { private: double ValuePerSquareUnit; protected: Shape(double valuePerSquareUnit): ValuePerSquareUnit(valuePerSquareUnit) { //error LNK2001: unresolved external symbol "public: virtual double __thiscall Shape::area(void)const " (?area@Shape@@UBENXZ) //std::cout << "creating shape, area = " << area() << std::endl; std::cout << "creating shape, value = " << value() << std::endl; //indirectly call pure virtual function in constructor } public: virtual double area() const = 0; double value() const { return ValuePerSquareUnit * area(); } virtual ~Shape() { printf("Shape::~Shape() is called"); } double getPerSquareUnit() { return ValuePerSquareUnit; } }; class Rectangle : public Shape { private: double Width; double Height; public: Rectangle(double width, double height, double valuePerSquareUnit): Shape(valuePerSquareUnit),Width(width),Height(height) { } virtual ~Rectangle() //can be removed { } virtual double area() const { return Width * Height; } }; class Circle: public Shape { double Radius; public: Circle(double radius, double valuePerSquareUnit): Shape(valuePerSquareUnit),Radius(radius) { } virtual ~Circle() //can be removed { } virtual double area() const { return PI * Radius * Radius; } }; int main() { Rectangle* pr = new Rectangle(30, 20, 10); Circle* pc = new Circle(15, 10); //invoke Rectangle::area() printf("rectangle: area = %.2f, PerSquareUnit = %.2f, value = %.2f/n", pr->area(), pr->getPerSquareUnit(), pr->value()); //invoke Circle::area() printf("circle : area = %.2f, PerSquareUnit = %.2f, value = %.2f/n", pc->area(), pc->getPerSquareUnit(), pc->value()); Shape* shape; shape = pr; printf("rectangle: area = %.2f, PerSquareUnit = %.2f, value = %.2f/n", shape->area(), shape->getPerSquareUnit(), shape->value()); shape = pc; printf("circle : area = %.2f, PerSquareUnit = %.2f, value = %.2f/n", shape->area(), shape->getPerSquareUnit(), shape->value()); return 0; }
CLR内部异常(上)
当我们提到CLR里的“异常”,要注意一个很重要的区别。有通过如C#的try/catch/finally暴露给应用程序,并由运行时提供机制全权实现的托管异常。也有运行时自己使用的异常。大部分运行时开发人员很少需要想到如何实现并暴露托管异常模型。但每个运行时开发人员都应该懂得CLR实现里是怎么使用异常的。为了保持区分,本文将托管程序抛出并捕捉的称为托管异常,而将运行时自己使用的错误处理方式称为 CLR内部异常。本文主要讨论CLR内部异常。
异常在什么地方有用?
异常几乎在所有地方都有用。最有用的地方就是抛出或捕捉异常的函数里,因为需要显式编写代码来抛出异常或者捕捉其并优雅的处理异常。即使一个函数本身不抛出异常,它也有可能调用抛出异常的函数。这样该函数必须在异常抛出的时候行为正常。明智的使用支持物(holders)可以极大简化正确编写这类代码。
为什么CLR内部异常是不同的?
CLR内部异常更像C++异常,但不完全是。CLR可以在Mac OSX、BSD还有Windows下编译。操作系统和编译器的差异使得我们不能仅使用标准C++的try/catch。另外,CLR内部异常还提供了类似托管代码的“finally”和“fault”这样的功能。
通过一些宏,编写异常处理代码就像标准C++那样简单。
捕捉异常
EX_TRY
最基本的宏是:EX_TRY / EX_CATCH / EX_END_CATCH,使用方法如下:
EX_TRY//调用一些函数,也许会抛出一个异常 Bar();
EX_CATCH//在这里,那就有错误发生了 m_finalDisposition =terminallyHopeless;
EX_END_CATCH(RethrowTransientExceptions)
CLR内部异常(中)
不捕捉某一个异常
常常有这种情况,代码不需要捕捉异常,但需要执行一些清理或者修正操作。虽然不总是,支持物(holders)经常用在这种场景里。在支持物(holders)不适用的情况里,CLR提供了两个“finally”块的变种。
EX_TRY_FOR_FINALLY
当需要在代码退出时执行修正操作时,一个finally块就比较合适。在CLR里有一系列的宏来实现try/finally:
EX_TRY_FOR_FINALLY//code EX_FINALLY//exit and/or backout code EX_END_FINALLY