C++ 中的catch(...)能捕获SHE异常吗

huangkaizl 2009-06-24 06:37:42
在VS2005中将工程的属性设置成为可以捕获SHE异常是不是在debug时候就能捕捉所有的异常阿。
急 急 急急!!!
...全文
371 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
DavidHsing 2009-06-25
  • 打赏
  • 举报
回复
SEH 是指应用程序未处理的异常他来处理,你看函数就明白了 ::SetUnhandledExceptionFilter
huangkaizl 2009-06-25
  • 打赏
  • 举报
回复
这个方法我在发帖子之前就已经使用过了好像不管用将SHE异常转换后再在后面加个catch(...)结果是catch(...)贴以下我的代码把
#include <dbghelp.h>
#include <tchar.h>
#include <afx.h>
#include <afxwin.h> // MFC core and standard components
#include <afxext.h> // MFC extensions
#include <afxdtctl.h> // MFC support for Internet Explorer 4 Common Controls
#ifndef _AFX_NO_AFXCMN_SUPPORT
#include <afxcmn.h> // MFC support for Windows Common Controls
#endif // _AFX_NO_AFXCMN_SUPPORT

#include <iostream>

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

///////////////////////////////////////////////////////////////////////////////
// Directives
//

#pragma comment ( lib, "dbghelp.lib")

///////////////////////////////////////////////////////////////////////////////
// Test data and code
//

// Contents of the user data streams
char Message1[] = "This is the first data stream...";
char Message2[] = "and this is the second data stream";

// Stream identifiers
// (LastReservedStream constant is defined in MINIDUMP_STREAM_TYPE
// enumeration in DbgHelp.h; all user data stream identifiers
// must be larger than LastReservedStream)
const ULONG32 cFirstStreamID = LastReservedStream + 1; //Last stream reserved for use by Windows Operating Systems.

const ULONG32 cSecondStreamID = LastReservedStream + 2;


///////////////////////////////////////////////////////////////////////////////
// Minidump creation function
//
void CreateMiniDump( EXCEPTION_POINTERS* pep, LPCTSTR lpszOupputDir)
{
// Open the file
TCHAR szFilePath[MAX_PATH * 2 +1] = {0}, szFileNam[32] = {0};
SYSTEMTIME tCurTime;
GetSystemTime(&tCurTime);
_stprintf(szFileNam, _T("MiniDump%04d%02d%02d%02d%02d%02d.dmp"), tCurTime.wYear, tCurTime.wMonth, tCurTime.wDay,
tCurTime.wHour, tCurTime.wMinute, tCurTime.wSecond);

_tmakepath(szFilePath, NULL, lpszOupputDir, szFileNam, NULL);
HANDLE hFile = CreateFile( szFilePath, GENERIC_READ | GENERIC_WRITE,
0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );

if( ( hFile != NULL ) && ( hFile != INVALID_HANDLE_VALUE ) )
{
// Create the minidump

// Exception information

MINIDUMP_EXCEPTION_INFORMATION mdei;

mdei.ThreadId = GetCurrentThreadId();
mdei.ExceptionPointers = pep;
mdei.ClientPointers = FALSE;

// Minidump type

MINIDUMP_TYPE mdt = MiniDumpNormal;

// User data streams

MINIDUMP_USER_STREAM UserStreams[2];

UserStreams[0].Type = cFirstStreamID;
UserStreams[0].Buffer = Message1;
UserStreams[0].BufferSize = sizeof(Message1);

UserStreams[1].Type = cSecondStreamID;
UserStreams[1].Buffer = Message2;
UserStreams[1].BufferSize = sizeof(Message2);

MINIDUMP_USER_STREAM_INFORMATION musi;

musi.UserStreamCount = 2;
musi.UserStreamArray = UserStreams;

// Call MiniDumpWriteDump

BOOL rv = MiniDumpWriteDump( GetCurrentProcess(), GetCurrentProcessId(),
hFile, mdt, (pep != 0) ? &mdei : 0, &musi, 0 );

if( !rv )
{
}

CloseHandle( hFile );
}
else
{

}

}

/////////////////////////////////////////////////////////////////////////////
#define INSTALL_SEHCONVERT() ExceptionConvert ecExceptionConvert

class ExceptionConvert
{
public:
ExceptionConvert(){OldFanc = _set_se_translator(trans_func); }
~ExceptionConvert(){_set_se_translator(OldFanc); }
private:
static void trans_func( unsigned int u, EXCEPTION_POINTERS* pExp )
{
throw pExp;
}
_se_translator_function OldFanc;
};
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
INSTALL_SEHCONVERT();

int nRetCode = 0;

// initialize MFC and print and error on failure
if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
{
// TODO: change error code to suit your needs
cerr << _T("Fatal Error: MFC initialization failed") << endl;
nRetCode = 1;
}
else
{
// TODO: code your application's behavior here.

try
{
cout << _T("begin") << endl;
/*vector<int> aaa;
aaa[1] = 0;*/
TCHAR *szTemp = NULL;
strcpy(szTemp, _T("1111111111111111111111111111111111111111"));
}
catch(EXCEPTION_POINTERS *pex)
{
CreateMiniDump(pex, _T("c:\\"));
}
catch(...)
{
}
}

return nRetCode;
}
huangkaizl 2009-06-25
  • 打赏
  • 举报
回复
呵呵 这个已经设置了,好像可以了
ggmfc 2009-06-25
  • 打赏
  • 举报
回复
UP!
  • 打赏
  • 举报
回复
按照C++标准是不能捕获的
这个看具体的异常处理实现...
fairchild811 2009-06-24
  • 打赏
  • 举报
回复
vs里面要用__try吧
lirongjun1985 2009-06-24
  • 打赏
  • 举报
回复
SHE 就是垃圾 唱歌贼难听
yuxinxxgc 2009-06-24
  • 打赏
  • 举报
回复
路过,顶顶
cnzdgs 2009-06-24
  • 打赏
  • 举报
回复
“项目属性”—“C/C++”—“代码生成”中将“启用C++异常”设置为“是,但有SEH异常(/EHa)”。
cutestar 2009-06-24
  • 打赏
  • 举报
回复
参考:
SEH是Windows系统提供的功能,跟开发工具无关。值得一提的是,VC将SEH进行了封装 try catch finally,c++中也可以用c的封装 __try{}__except(){} 和 __try{}__finally{}. 所以当你建立一个C++ try块时,编译器就生成一个SEH__try块。一个C++catch测试变成一个SEH异常过滤器,并且catch中的代码变成SEH__except块中的代码。实际上,当你写一条C++ throw语句时,编译器就生成一个对Windows的RaiseException函数的调用。用于throw语句的变量传递给RaiseException作为附加的参数。

catch(...)能捕获所有的异常(应该是绝大部分),但要放到所有catch段的最后,但不能获取详细的信息.
要是想了解更多,看看<windows核心编程>,里面有章就是讲这个
Gothic_girl 2009-06-24
  • 打赏
  • 举报
回复
仅供参考:

1. Windows SEH 与 C++ Exception

1) Windows SEH 结构化异常

结构化异常是Windows 操作系统提供的与语言无关的异常处理机制, SHE使用Win32API中的RaiseException()函数来抛出异常,在VC中使用关键字__try和关键字__except来捕获,并用宏函数GetExceptionCode和GetExceptionInfo来获取捕获的异常由什么原因产生,和产生异常时环境状态。__finally关键字保证无论是否发生异常,finally代码段都会被执行。

SHE使用示例代码

int ECode;

__try

{

__try

{

RaiseException(1, // 抛出异常码为1的SEH异常

0,

0, NULL); // 没有参数

}

__finally

{

printf("2 "); // 不管是否有异常,必定会执行的代码

}

}

__except (ECode=GetExceptionCode())

{

printf("发生异常,Code=%d\n",ECode); // 捕获异常后执行的代码 ;

}

输出结果:

2发生异常,Code=1

2) C++Exception

C++标准也提供了一种异常处理机制,通过使用try,catch,throw关键字来表达,在C++异常可以通过throw函数来抛出简单变量,复杂变量与异常对象,与Windows异常相比,异常对象可以给开发者提供更多的信息。

try

{

//正常代码

。。。

throw CExcetion();

。。。

}

catch (CException* e)

{

//处理异常代码

}

3) SEH 到 C++异常的转换

在同一个程序中,如果使用WIN32API它会抛出SHE,使用C++库函数,它们又会抛出C++异常,Win32API和C++函数混和使用时如果使用两种异常捕获机制时,使用起来会影响程序的可读性,因此C++运行库提供了_set_se_translator函数,在SHE异常发生时通过回调方式来转换SEH异常为C++异常。在此提供一个转换的宏来实现转换。

转换宏的代码:

#define INSTALL_SEHCONVERT() ExceptionConvert ecExceptionConvert

class SEHException

{

private:

unsigned int nSE;

public:

SEHException() {}

SEHException( unsigned int n ) : nSE( n ) {}

~SEHException() {}

unsigned int getSeNumber() { return nSE; }

};

class ExceptionConvert

{

public:

ExceptionConvert(){OldFanc = _set_se_translator(trans_func); }

~ExceptionConvert(){_set_se_translator(OldFanc); }

private:

static void trans_func( unsigned int u, EXCEPTION_POINTERS* pExp )

{

throw SEHException(u);

}

_se_translator_function OldFanc;

};

使用上面INSTALL_SEHCONVERT宏后就可以使用如下代码来捕获SHE异常了

INSTALL_SEHCONVERT();

Try

{



}

catch(SEHException &seh){



}

2. 同步异常与异步异常

1) VC的C++ Exception 采用两种模式捕获异常:同步模式和异步模式。VC的工程的调试版本缺省使用异步模式,工程的发布版本缺省使用同步模式。在同步模式下,VC的编译器假定代码中只有在显示使用throw和调用函数的时候才会引发异常,因此,在同步模式下,VC编译出的代码比较小,但在这种模式下,try-catch对不能捕获内存访问异常与算术除零异常等。在异步模式下,VC的编译器为try块内的每一条语句生成异常捕获代码,在这种情况下,他能够捕获全部的异常,还能保证栈上对象在解栈中正确释放。为了要在发行版本中也能够捕获全部异常就需要打开异步模式,但代价是程序编译出代码变大,运行速度变慢。

2)编译选项:

同步模式的编译选项为/EHs或者/GX(等同于/EHsc)

异步模式的编译选项为/EHa

3. 多线程下的异常捕获

在创建线程并运行线程的函数中把创建线程的代码放在try块中并不会捕获到线程函数中发生的异常,线程函数中发生的异常只能在线程函数中捕获。并且每一个线程都需要自己的SHE转换宏。转换宏可以放在线程函数的开始部分

4.参考MSDN库
skyxie 2009-06-24
  • 打赏
  • 举报
回复
SEH, 如果是用的MS的complier,就必须使用 __try

其他编译器不清楚
huangkaizl 2009-06-24
  • 打赏
  • 举报
回复
补充一下只用try catch 不用 __try __catch

16,472

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧