您的位置:首页 > 编程语言

windows核心编程 第1章 错误处理

2016-06-06 11:29 441 查看
好吧,我承认我是个很懒的人,很多内容是从别人那里复制的。。。不过加了自己的实践,有意外的地方,以后的实验的环境默认为win7x64,Visual Studio 2008,红色的一般是我出意外的地方=_=主要参考:http://www.cppblog.com/SpringSnow/archive/2009/02/20/74350.html

       这一章开篇介绍了windows函数的几种返回值:VOID,BOOL,HANDLE,PVOID,LONG/DWORD。让我们明白,仅仅通过返回值,我们是不能清楚函数调用为什么会失败的。windows内部,函数检测到错误会采用什么机制呢?它是采用“线程本地存储区”的机制来讲相应的错误代码与“主调线程”关联到一起。它可以使不同的线程能独立运行,不会出现相互干扰对方的错误代码的情况。
错误代码:一个Windows函数返回的错误代码对了解该函数为什么会运行失败常常很有用。Microsoft公司编译了一个所有可能的错误代码的列表(存放在WinError.h头文件中),并且为每个错误代码分配了一个32位的号码;
线程本地存储器:thread-local storage,当一个Windows函数检测到一个错误时,它会使用一个称为线程本地存储器的机制,将相应的错误代码与调用的线程关联起来,这将使线程能够互相独立地运行,而不会影响各自的错误代码;
GetLastError函数:GetLastError函数返回一个32位的错误代码,它主要用于两种情况:1)确定是什么样的错误,此时当Windows函数运行失败时,应该立即调用GetLastError函数,如果调用了另一个Windows函数,它的值很可能被改写;2)搞清楚成功的原因是什么,有些Windows函数之所以能成功运行,其中的原因有很多,比如CreateEvent函数运行成功,既可能是因为你实际创建了该对象,也有可能是因为已经存在带有相同名字的事件内核对象,此时可以调用GetLastError函数可以搞清函数运行成功的原因;
SetLastError函数:SetLastError函数用于设定线程最后的错误代码,这个错误代码既可以是Windows系统自定义的(代码的第29位必须为0),也可以是用户自定义的(代码的第29位必须为1);
FormatMessage函数:FormatMessage函数用于将错误代码转换成它的文本描述;
         函数返回的时候,其返回值会指出已发生的一个错误。         我们查看具体是什么错误,在相应的函数执行完成后调用GetLastError()即可。
         windows中,错误有三种表示:         一个消息ID(如ERROR_PATH_NOT_FOUND)            消息文本(如the system cannot find the path specified)         一个编号(尽量避免使用)
         调试程序的时候,我们可以配置watch窗口,让它始终显示线程的上一个错误代码和错误的文本描述。如$err,hr。hr是要显示错误代码的消息文本。

 

 

         那么我们怎么在自己的程序中显示消息文本呢?文章介绍了利用FormatMessage函数。这里我也介绍一下这个函数的用法:                  DWORD FormatMessage(             DWORD dwFlags,             LPCVOID lpSource,             DWORD dwMessageId,             DWORD dwLanguageId,             LPTSTR lpBuffer,             DWORD nSize,             va_list* Arguments             );
         dwFlags:         # FORMAT_MESSAGE_ALLOCATE_BUFFER // 此函数会分配内存以包含描述字串。         # FORMAT_MESSAGE_FROM_SYSTEM,  // 在系统的id映射表中寻找描述字串         # FORMAT_MESSAGE_FROM_HMODULE  // 在其他资源模块中寻找描述字串         # FORMAT_MESSAGE_FROM_STRING   // 消息ID是个字串,不是个DWORD         #FORMAT_MESSAGE_IGNORE_INSERTS // 允许我们获得含有%占位符的消息,不传递这个标志,就必须在Arguments参数中提供这些占位符的信息         通常为:FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM
         lpSource:         # 指定了FORMAT_MESSAGE_FROM_HMODULE的话,此参数表示模块的HANDLE         # 指定了FORMAT_MESSAGE_FROM_STRING的话,此参数表示id字串         通常为:NULL
         dwMessageId:         消息ID;如果指定FORMAT_MESSAGE_FROM_STRING,将被忽略。
         dwLanguageId:         消息描述所用的语言         通常为:0表示自动选择
         lpBuffer:         #如果未指定FORMAT_MESSAGE_ALLOCATE_BUFFER,则为自己提供的缓冲区         #否则为系统LocalAlloc分配,需要被用户LocalFree
         nSize:         #如果未指定FORMAT_MESSAGE_ALLOCATE_BUFFER,则为自己提供的缓冲区大小         #否则为系统LocalAlloc分配之最小缓冲区大小
         Arguments:         通常不使用                     代码如下:      
 void ShowError(){	//DWORD dwError = GetLastError();	DWORD dwError = 5L;	HLOCAL hlocal = NULL;
// Use the default system locale since we look for Windows messages. // Note: this MAKELANGID combination has 0 as value DWORD systemLocale = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL);
BOOL fOk = FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_ALLOCATE_BUFFER,  NULL, dwError, systemLocale,  (PTSTR) &hlocal, 0, NULL);
if (!fOk) { // Is it a network-related error? HMODULE hDll = LoadLibraryEx(TEXT("netmsg.dll"), NULL,  DONT_RESOLVE_DLL_REFERENCES);
if (hDll != NULL) { fOk = FormatMessage( FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_ALLOCATE_BUFFER, hDll, dwError, systemLocale, (PTSTR) &hlocal, 0, NULL); FreeLibrary(hDll); } }
if (fOk && (hlocal != NULL)) { //这个输出可以在VS的“输出窗口”看到               //LocalLock锁定一个本地内存项目 并且 返回一个指向内存块第一个Byte的指针 OutputDebugString((PCTSTR) LocalLock(hlocal)); //这里要把项目属性改为 多字节字符集,不然会出现乱码 cout<<(PCTSTR) LocalLock(hlocal)<<endl; LocalFree(hlocal); }}


 

  visual studio 也提供了一个查询错误的小工具,为Error Lookup。通过以上的示例,我们就知道其相应的工作原理。在“工具”里可以找到。

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: