说三道四技术文摘-感悟人生的经典句子
说三道四 > 文档快照

关于捕获硬件异常和软件异常的问题

编辑:说三道四文库 发布时间:2018-07-16 04:15
HTML文档下载 WORD文档下载 PDF文档下载
通常soft exception我们用
try
{
}
catch(...)
{
}

hardware exception用
__try
{
}
__exception(...)
{
}


__try
{
}
__finally
{
}


但是他们不能互相包容,也就是指不能这样写:
__try
{
  try
  {
  }
  catch(...)
  {
  }
}
__exception(...)
{
}

但是如果我需要同时捕获一段代码中所有的硬件异常和软件异常,这时怎么办呢?
求大虾指点~

谢谢~~~
gz
You cannot use both __try/__except (structured exception handling) and try/catch (C++ exception handling) in the same function

but you can like that:
#include <stdio.h>
void test();
int main(int argc, char* argv[])
{
puts("hello");
try
{
test();
  puts("in try");
}
catch(...)
{
puts("in catch");
}
puts("world");
return 0;
}
void test()
{
int* p = 0x00000000;   // pointer to NULL

__try{
puts("in __try");
*p = 13;    // causes an access violation exception;
}
__except(puts("in __except"), 1)
{
puts("in __except");
}
}
同意 phiger(phiger)
谢谢,我已经解决:

Exception Handling Differences
Home |  Overview |  How Do I |  FAQ

The major difference between structured exception handling and C++ exception handling is that the C++ exception handling model deals in types, while the C structured exception handling model deals with exceptions of one type — specifically, unsigned int. That is, C exceptions are identified by an unsigned integer value, whereas C++ exceptions are identified by data type. When an exception is raised in C, each possible handler executes a filter that examines the C exception context and determines whether to accept the exception, pass it to some other handler, or ignore it. When an exception is thrown in C++, it may be of any type.

A second difference is that the C structured exception handling model is referred to as “asynchronous” in that exceptions occur secondary to the normal flow of control. The C++ exception handling mechanism is fully “synchronous,” which means that exceptions occur only when they are thrown.

If a C exception is raised in a C++ program, it can be handled by a structured exception handler with its associated filter or by a C++ catch handler, whichever is dynamically nearer to the exception context. For example, the following C++ program raises a C exception inside a C++ try context:

#include <iostream.h>

void SEHFunc( void );

int main()
{
    try
    {
        SEHFunc();
    }
    catch( ... )
    {
        cout << "Caught a C exception."<< endl;
    }
    return 0;
}
void SEHFunc()
{
    __try
    {
        int x, y = 0;
        x = 5 / y;
    }
    __finally
    {
        cout << "In finally." << endl;
    }
}

This is the output from the preceding example:

In finally.
Caught a C exception.

C Exception Wrapper Class
In a simple example like the above, the C exception can be caught only by an ellipsis (...) catch handler. No information about the type or nature of the exception is communicated to the handler. While this method works, in some cases you may need to define a transformation between the two exception handling models so that each C exception is associated with a specific class. To do this, you can define a C exception "wrapper" class, which can be used or derived from in order to attribute a specific class type to a C exception. By doing so, each C exception can be handled by a C++ catch handler more separately than in the preceding example.

Your wrapper class might have an interface consisting of some member functions that determine the value of the exception, and that access the extended exception context information provided by the C exception model. You might also want to define a default constructor and a constructor that accepts an unsigned int argument (to provide for the underlying C exception representation), and a bitwise copy constructor. The following is a possible implementation of a C exception wrapper class:

class SE_Exception
{
private:
    SE_Exception() {}
    SE_Exception( SE_Exception& ) {}
    unsigned int nSE;
public:
    SE_Exception( unsigned int n ) : nSE( n ) {}
    ~SE_Exception() {}
    unsigned int getSeNumber() { return nSE; }
};

To use this class, you install a custom C exception translation function that is called by the internal exception handling mechanism each time a C exception is thrown. Within your translation function, you can throw any typed exception (perhaps an SE_Exception type, or a class type derived from SE_Exception) that can be caught by an appropriate matching C++ catch handler. The translation function can simply return, which indicates that it did not handle the exception. If the translation function itself raises a C exception, terminate is called.

To specify a custom translation function, call the _set_se_translator function with the name of your translation function as its single argument. The translation function that you write is called once for each function invocation on the stack that has try blocks. There is no default translation function; if you do not specify one by calling _set_se_translator, the C exception can only be caught by an ellipsis catch handler.

For example, the following code installs a custom translation function, then raises a C exception that is wrapped by the SE_Exception class:

#include <stdio.h>
#include <eh.h>
#include <windows.h>

class SE_Exception {
private:
    SE_Exception() {}
    SE_Exception( SE_Exception& ) {}
    unsigned int nSE;
public:
    SE_Exception(unsigned int n) : nSE(n) {}
    ~SE_Exception() {}
    unsigned int getSeNumber() { return nSE; }
};

void SEFunc(void);
void trans_func( unsigned, _EXCEPTION_POINTERS*);

int main()
{
    _set_se_translator( trans_func );
    try
    {
        SEFunc();
    }
    catch( SE_Exception e )
    {
        printf( "Caught a __try exception with SE_Exception.\n" );
        printf( "nSE = 0x%x\n", e.getSeNumber() );
    }
    return 0;
}
void SEFunc()
{
    __try
    {
        int x, y=0;
        x = 5 / y;
    }
    __finally
    {
        printf( "In finally\n" );
    }
}
void trans_func( unsigned int u, _EXCEPTION_POINTERS* pExp )
{
    printf( "In trans_func.\n" );
    throw SE_Exception( u );

不过我用更简单的方法解决了,以下是源码,散分:

// std35.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <iostream.h>
#include <excpt.h>
#include <eh.h>
#include <windows.h>

void trans_func(unsigned int eCode, _EXCEPTION_POINTERS* pExp)
{
switch (eCode)
{
case EXCEPTION_ACCESS_VIOLATION:
throw exception("The thread tried to read from or write to a virtual address for which it does not have the appropriate access.");

case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
throw exception("The thread tried to access an array element that is out of bounds and the underlying hardware supports bounds checking.");

case EXCEPTION_BREAKPOINT:
throw exception("A breakpoint was encountered.");

case EXCEPTION_DATATYPE_MISALIGNMENT:
throw exception("The thread tried to read or write data that is misaligned on hardware that does not provide alignment. For example, 16-bit values must be aligned on 2-byte boundaries; 32-bit values on 4-byte boundaries, and so on.");

case EXCEPTION_FLT_DENORMAL_OPERAND:
throw exception("One of the operands in a floating-point operation is denormal. A denormal value is one that is too small to represent as a standard floating-point value.");

case EXCEPTION_FLT_DIVIDE_BY_ZERO:
throw exception("The thread tried to divide a floating-point value by a floating-point divisor of zero.");

case EXCEPTION_FLT_INEXACT_RESULT:
throw exception("The result of a floating-point operation cannot be represented exactly as a decimal fraction.");

case EXCEPTION_FLT_INVALID_OPERATION:
throw exception("This exception represents any floating-point exception not included in this list.");

case EXCEPTION_FLT_OVERFLOW:
throw exception("The exponent of a floating-point operation is greater than the magnitude allowed by the corresponding type.");

case EXCEPTION_FLT_STACK_CHECK:
throw exception("The stack overflowed or underflowed as the result of a floating-point operation.");

case EXCEPTION_FLT_UNDERFLOW:
throw exception("The exponent of a floating-point operation is less than the magnitude allowed by the corresponding type.");

case EXCEPTION_ILLEGAL_INSTRUCTION:
throw exception("The thread tried to execute an invalid instruction.");

case EXCEPTION_IN_PAGE_ERROR:
throw exception("The thread tried to access a page that was not present, and the system was unable to load the page. For example, this exception might occur if a network connection is lost while running a program over the network.");

case EXCEPTION_INT_DIVIDE_BY_ZERO:
throw exception("The thread tried to divide an integer value by an integer divisor of zero.");

case EXCEPTION_INT_OVERFLOW:
throw exception("The result of an integer operation caused a carry out of the most significant bit of the result.");

case EXCEPTION_INVALID_DISPOSITION:
throw exception("An exception handler returned an invalid disposition to the exception dispatcher. Programmers using a high-level language such as C should never encounter this exception.");

case EXCEPTION_NONCONTINUABLE_EXCEPTION:
throw exception("The thread tried to continue execution after a noncontinuable exception occurred.");

case EXCEPTION_PRIV_INSTRUCTION:
throw exception("The thread tried to execute an instruction whose operation is not allowed in the current machine mode.");

case EXCEPTION_SINGLE_STEP:
throw exception("A trace trap or other single-instruction mechanism signaled that one instruction has been executed.");

case EXCEPTION_STACK_OVERFLOW:
throw exception("The thread used up its stack.");

default:
throw exception("Unknow exception!");
}
}

#include <vector>

void Run()
{
int sz[2];
int *p1 = 0x00000000;
int *p2;

std::vector<int> vec(4);

throw exception("nothing");

int a=5, b=0;
a = a / b;
*p1 = 1;
a = vec[1000];
*p2 = 2;
}

void Func()
{
__try
{
Run();
}
__finally
{
cout << "finally" << endl;
}
}

int main(int argc, char* argv[])
{
_set_se_translator( trans_func );
try
{
Func();
}
catch(exception &e)
{
cout << e.what() << endl;
}

cout << "game over" << endl;

return 0;
}
??????????????????
备案号:鲁ICP备13029499号-2 说三道四 www.s3d4.cn 说三道四技术文摘