一天一个C Run-Time Library 函数 __isascii & iswascii & __toascii
write by 九天雁翎(JTianLing) -- www.jtianling.com
msdn:
Determines whether a particular character is an ASCII character.
int __isascii(
int c
);
int iswascii(
wint_t c
);
测试程序:
#include "stdafx.h"
#include "ctype.h"
#include "locale.h"
#include "stdio.h"
void CheckCharAndPrint(char acChar)
{
if(__isascii(acChar))
{
printf("char %c is a ascii char./n",acChar);
}
else
{
// 此处无法正常输出中文,没有深入研究了
printf("char %c is not a ascii char./n",acChar);
}
}
void CheckWCharAndPrint(wchar_t awcChar)
{
if(iswascii(awcChar))
{
wprintf(L"wchar %c is a ascii char./n",awcChar);
}
else
{
setlocale(LC_ALL,"");
wprintf(L"wchar %c is not a ascii char./n",awcChar);
}
}
int _tmain(int argc, _TCHAR* argv[])
{
char lcC = 'a';
char lcD = '中';
CheckCharAndPrint(lcC);
CheckCharAndPrint(lcD);
wchar_t lwcC = L'a';
wchar_t lwcD = L'中';
CheckWCharAndPrint(lwcC);
CheckWCharAndPrint(lwcD);
return 0;
}
说明:
__isascii是一个比较特殊的函数,因为它以两个前置下划线开头。这在C语言中并不多见。(起码我看到的比较少)
此函数应该不属于标准库函数,《TCPL》中,《C语言参考》中并没有描述,但是gcc中有此函数。也就是说linux下也能正常使用此函数。
iswascii这个__isascii函数的宽字节版本,如同很多宽字节版本的函数一样,这个函数属于MS自己扩的,于是。。linux下无法使用此函数,要使用,只能自己实现罗。
实现:
MS:
#define __isascii(_Char) ( (unsigned)(_Char) < 0x80 )
inline int __cdecl iswascii(wint_t _C) {return ((unsigned)(_C) < 0x80); }
gcc:
#define __isascii(c) (((c) & ~0x7f) == 0) /* if C is a 7 bit value*/
__isascii都是一个简单的宏。MS的iswascii原理和其__isascii都一样,仅仅是一个内联的函数。
微软的实现是依赖于字符小于128(0x80),这里还做了一次强转,不是太理解,因为实际char可以直接作为整数来比较,也许仅仅是为了屏蔽warning?
gcc的实现是依赖于字符除低七位外无任何其他值。即先将127(0x7f)取反,再与字符位与。实际就是取得字符c除了低七位以外的值。再比较此值是否为零。
想不到一个这样简单的函数,MS,gcc的实现差别都这么大,相对而言MS的实现自然是比较浅显易懂的,但是gcc用这么复杂的实现,应该有更好的效率。
就分析而言,强转+小于操作 运行时间大于 一次取反一次位与一次等于操作。还真不容易知道谁的效率真的更高。那么就测试一下吧。
效率测试:
#include "jtianling.h"
#define __isasciims(_Char) ( (unsigned)(_Char) < 0x80 )
#define __isasciigcc(c) (((c) & ~0x7f) == 0) /* if C is a 7 bit value*/
const int DEF_TEST_TIMES = 1000000000;
void CheckMS(char ac)
{
double ldTimeLast = jtianling::GetTime();
for (int i=0; i<DEF_TEST_TIMES ; ++i)
{
__isasciims(ac);
}
double ldTimePast = jtianling::GetTime() - ldTimeLast;
printf("__isasciims %c run %d times cost %lf secs./n", ac, DEF_TEST_TIMES, ldTimePast);
}
void Checkgcc(char ac)
{
double ldTimeLast = jtianling::GetTime();
for (int i=0; i<DEF_TEST_TIMES ; ++i)
{
__isasciigcc(ac);
}
double ldTimePast = jtianling::GetTime() - ldTimeLast;
printf("__isasciigcc %c run %d times cost %lf secs./n", ac, DEF_TEST_TIMES, ldTimePast);
}
int _tmain(int argc, _TCHAR* argv[])
{
char lc = 'a';
char lc2 = '中';
CheckMS(lc);
Checkgcc(lc);
CheckMS(lc);
Checkgcc(lc2);
return 0;
}
至于GetTime函数的意义,请参考我以前写的库,无非就是获取当前时间,不知道也没有关系。你可以用time(NULL)来替代,只不过精度没有这个函数高而已。
实际的测试结果很让人失望,在测试了几乎无数次以后,MS和gcc的实现效率都几乎相同,在10亿这个级别,gcc也不过有时快0.1秒而已,而且多次运行,还不是太稳定。看来并不是复杂的实现就一定好。。。
相关函数:
msdn:
Converts characters.
int __toascii(
int c
);
这个函数也是一个双前置下划线的函数,MS,gcc中都有实现。而且在此时,实现都是一样的。
#define __toascii(_Char) ( (_Char) & 0x7f )
gcc注释到 “mask off high bits.”
这里和gcc中__isascii函数实现的前一部分很像,一个是去除低七位,一个是保留低七位。看了这个以后才知道gcc为什么想到这样实现__isascii了。
个人想法:
这两个函数在实际中我从来没有用到过,假如不是我工作范围太窄那就是这两个函数的使用性并不强了,的确,我没有事去把一个值转为ascii?是ascii的话就没有意义,不是的话,原来的含义还能保留吗?至于__isascii函数可能还在某些情况下有用吧,只不过我没有用到过,谁有实际中使用此两个函数的代码可以告诉我一下。
另外,总结的是,虽然C Runtime库MS也有源码,但是完全没有任何注释。相对而言gcc的注释就算是很丰富和详细了,呵呵,毕竟开源代码就是不一样啊,做来就是给人看的,想想这样分析下去,光是看源代码收获都不会太小。
最后。。。。。。。。。。。这样一个最最简单的函数,宏定义的函数。用了我整整一个没有加班的晚上的,晕掉了。当然,有在家里的VS中编程已经不太习惯的因素,但是还是太过了,下次不能这样太过了。。。点到为止就好了,不然这一辈子都分析不完了。
write by 九天雁翎(JTianLing) -- www.jtianling.com
阅读全文....
呵呵,是关于lua stdlib 库的set模块的bug,其实作者好像确认很久了。。。。但是我这段时间一直没有上gmail,所以没有看到。。。作者说,在新版中已经修改此bug...今天下了最新版,发现真是这样:)呵呵,真高兴啊,吸收了开源社区的那么多营养。。。总算有点报答了。。。当然,这仅仅是起步:)
实际流程贴一下。。。满足一下虚荣心。。。其实仅仅是一个很小的很容易发现的bug。。。呵呵,我当时学lua才一两周。。也不可能发现多么难的bug....lol
原来的lua stdlib set中某段程序如下:
- -- @func propersubset: Find whether one set
is
a proper subset of
- -- another
- -- @param s, t: sets
- -- @returns
- -- @param r: true
if
s
is
a proper subset of t, false otherwise
- function propersubset (s, t)
-
return
subset (s, t)
and
not
subset (t, s)
- end
- -- @func equal: Find whether two sets are equal
- -- @param s, t: sets
- -- @returns
- -- @param r: true
if
sets are equal, false otherwise
- function equal (s, t)
-
return
subset (s, t)
and
subset (s, t)
- end
- -- @head Metamethods
for
sets
- -- set + table = union
- metatable.__add = union
- -- set - table = set difference
- metatable.__sub = difference
- -- set / table = intersection
- metatable.__div = intersection
- -- set <= table = subset
- metatable.__le = subset
于是我发邮件给作者
hi all,
Thank you very much for your hard working with the LuaForWindows,I enjoy it so mush.
there is a bug to report as my return.
the set.lua file in the lualibs, 117th line.
source as this code:"return subset (s, t) and subset (s, t)"
it obviously should be "return subset (s,t) and subset(t, s)"
which means they are equal when s is the subset t and t is the subset s.
I hope I'm right and didn't disturb you.
BTW,there is a surprising attribute.
In the set's operations,div(/) mean intersection that is different from custom.
In the custom mul(*) denotes it,just like the <<programming in Lua>> writes in the 13th captial named "metatable and meatmethod"
Thank you for reading my poor Chinglish. lol,I'm Chinese.
Best wishes.
your honest
JTianLing from jtianling{at}gmail.com
luaforwindows的作者回信
Andrew Wilson to me, rrt, luaforwindows
show details Sep 3 Reply
Thanks for the bug report JTianLing, this particular module comes from
the stdlib library , I'll copy your report of this issue to the
administrator of that project http://luaforge.net/projects/stdlib/
.
Your English is great, you wouldn't want to even hear my Mandarin.
关心
Andrew Wilson
呵呵,不知道他这里说关心是什么意思......,惊奇的是。。。。他竟然还真能打中文字。。。。E文系统应该是没有中文输入法的吧。。。。
最后lua stdlib的作者回信:
Reuben Thomas to Andrew, me, luaforwindows
show details Sep 4 Reply
Thanks, this is quite correct. I've made a new release with this fix.
I see, I had actually forgotten that * is used in Modula-3 in the same way. I am happy to change this so that * is intersection and / is symmetric difference.
Thanks, I've made another release with these changes, and coincidentally fixed set.difference, which was also broken.
呵呵,最新版的set如下,可见已经修复,并且连那个我称为surprising attribute 的“/”符号表示交集也改了:)
- -- @func intersection: Find the intersection of two sets
- -- @param s, t: sets
- -- @returns
- -- @param r: set intersection of s
and
t
- function intersection (s, t)
- local r = new {}
-
for
e
in
elements (s) do
-
if
member (t, e) then
- insert (r, e)
- end
- end
-
return
r
- end
- -- @func union: Find the union of two sets
- -- @param s, t: sets
- -- @returns
- -- @param r: set union of s
and
t
- function union (s, t)
- local r = new {}
-
for
e
in
elements (s) do
- insert (r, e)
- end
-
for
e
in
elements (t) do
- insert (r, e)
- end
-
return
r
- end
- -- @func subset: Find whether one set
is
a subset of another
- -- @param s, t: sets
- -- @returns
- -- @param r: true
if
s
is
a subset of t, false otherwise
- function subset (s, t)
-
for
e
in
elements (s) do
-
if
not
member (t, e) then
-
return
false
- end
- end
-
return
true
- end
- -- @func propersubset: Find whether one set
is
a proper subset of
- -- another
- -- @param s, t: sets
- -- @returns
- -- @param r: true
if
s
is
a proper subset of t, false otherwise
- function propersubset (s, t)
-
return
subset (s, t)
and
not
subset (t, s)
- end
- -- @func equal: Find whether two sets are equal
- -- @param s, t: sets
- -- @returns
- -- @param r: true
if
sets are equal, false otherwise
- function equal (s, t)
-
return
subset (s, t)
and
subset (t, s)
- end
- -- @head Metamethods
for
sets
- -- set + table = union
- metatable.__add = union
- -- set - table = set difference
- metatable.__sub = difference
- -- set * table = intersection
- metatable.__mul = intersection
- -- set / table = symmetric difference
- metatable.__div = symmetric_difference
- -- set <= table = subset
- metatable.__le = subset
- -- set < table = proper subset
- metatable.__lt = propersubset
这虽然是一件芝麻一样的小事,但却是我个人第一次真正的为开源社区做贡献。。。。虽然仅仅是以bug report的形式:)立此存照:)
阅读全文....
最近一段时间学了很多东西,因为时间只有这么多,工作时间太长,空闲时间太少,虽然我几乎用了全部的空闲时间来学习,
但是还是相对而言忽略了实践。
最近看了《lua程序设计》,《python核心编程》,《bash高级编程》,几乎是新学了3门语言(就是python以前还学过一些),
而实际实践的内容无非就是跟着数本简单的敲敲代码,远远不够。。。。接下来应该可以脱离纯粹的语言学习阶段。。。多多实践一下了,这样的阶段应该博客也会多写一些的:)光看书实在没有什么太多好写的:)
计划是一边重新学习数据结构。。。(不知道是第几次重新了,没有一次真正的做到看透全书,做完全部习题。。。。)
一般用上述3种语言+c/c++(吃饭的家伙)来完成学习中的突然想法:)比如以前提到的makefile自动生成和linux/windows通用服务器开发库。。。。。
阅读全文....
解决方法竟然是。。。。。。。在xp下安装的文件全部打包。。。。然后后放到vista下再解压就可以在vista下用了。。。彻底无语。。。。问题看来和程序无关,仅仅是安装的问题。
阅读全文....
假如你也一直开发的都是windows,linux下都能跑的程序,关于目录的使用你肯定就和我一样统一了,都是用"/"来表示。道理很简单,因为linux不支持"/"而windows支持"/",一直以来都是这样,linux原生的"/"使用自然没有任何问题,windows下的fopen,CreateFile,OpenFile,CreateProcess等等使用的也不是一次两次了,用的也都没有问题。当然,今天,问题来了,一碰到就调试的人郁闷的要死。
关于SHFileOperation的。此该死的函数,没有错误返回代码,只能知道执行失败,通过GetLastError返回的甚至可能是在MSDN中SystemError说明以外的数值。于是,噩梦开始了。当我用按照习惯的使用"/"来表示目录,并测试代码,在目录只有一层的时候是可以成功的,即类似E:/data的目录执行没有问题。但目录为很多层的时候,SHFileOperation竟然也有时能够成功,但是有时却会失败,输入参数我一再验证没有问题。(输入参数以双零结尾也是需要注意的),直到我崩溃。准备直接用CreateProcess调用copy /y ,del 等命令来完成任务的时候,才想起来"/"在dos(windows所谓的的shell吧)中用来表示参数。。。。用"/"表示目录来调用dos命令总是会失败的。。。。。。。才联想到SH的名字。。。SHell啊。。。。。一切都明白了。。。。需要说明的是,这一点MSDN中没有任何说明,并且,即使我使用"/"来表示目录并调用SHFileOperation竟然还有成功的时候。。。。更多时候也不是完全失败,而且进行了一半。。。。。。。太没有天理了,还没有ErrorCode。。。。。。。
另外,今天在寻找一些解压的库,用来完成监控系统中的更新操作。找了一下午,zlib,7-zip的支持库等,找了一圈,不是不支持rar就是用法不明,或者不支持linux,最后发现都不适合,而unrar这个命令行工具其实就完成可以完成任务。。。。。。。无非就是一个熟悉的CreateProcess而已,感叹不已,想起来我以前学习的时候还特意怀旧般的为DOS命令写了一系列文章,到了工程应用的时候竟然都忘了。。。。其实有的时候用命令行提供给你的工具,比找个库要简单的多。。。。
阅读全文....
实际在我的电脑上效果和作者所说有差异,不管我怎么运行,都是稳定的结果
而作者说放在后台的循环可能后运行。(意思大概就是像多进程和多线程一样)
其实在我的电脑上运行不管怎么样都是一样的,如图,呵呵,其实把我的电脑用户名都透露出去了-_-!
阅读全文....
一方面自己在别的地方可以看到:)
其实想想以前,vim的配置无非就是看看别人的很长的配置文件,自己照着copy一下,现在基本上形成了自己的习惯了,有什么需要的自己加入快捷键了,特别是以“,”(逗号)开始的leader使用起来非常的方便,虽然其实是牺牲了一个重复反向查找的功能。。。。但是实际中,我没有有过用到","这样奇怪的需求,所以覆盖了也不怎么可惜。
可惜的是发上来的文件没有语法高亮。。。。。。。。。。
let mapleader=","
set encoding=utf-8
set ambiwidth=double
set nocompatible
set hls
set nu
set ai
colors desert
syntax on
set sw=4
set ts=4
"set autocmd
set smarttab
set whichwrap+=h,l,~,b,s,<,>,[,]
set helplang=cn
set ruler
set showcmd
filetype plugin indent on
set nomagic
set mouse=a
set cmdheight=2
set backspace=eol,start,indent
set showmatch
set wildmenu
"-----------------------------------------------------------
" for snippetsEmu_key but it's snippet file is not created
"-----------------------------------------------------------
let g:snippetsEmu_key = "<S-Tab>"
"-----------------------------------------------------------
" folding
"-----------------------------------------------------------
"enable folding, i find it very useful
set nofen
set fdl=0
set lbr
set si
set wrap
"-----------------------------------------------------------
" some key I maped and liked
"-----------------------------------------------------------
" I like use <space> <bs> <cr> key in normal mode
nmap <space> i<space><esc>l
nmap <bs> i<bs><esc>l
nmap <cr> i<cr><esc>
" sometimes use this to p sth in new line
nmap <leader>o o<esc>p
nmap <leader>O O<esc>p
" one key to save even in insert mode
nmap <f2> :w<cr>
imap <f2> <esc>:w<cr>a
" select all :) like microsoft's CTRL-A
nmap <leader>a ggVG
"-----------------------------------------------------------
" for favarite c/c++
"-----------------------------------------------------------
" normal mode
autocmd filetype c map<silent><buffer> <f6> :w<cr>:make<cr>:cw<cr>
autocmd filetype cpp map<silent><buffer> <f6> :w<cr>:make<cr>:cw<cr>
"-----------------------------------------------------------
" For special script file type
" I only need to use python,lua,sh and surely only know these
"-----------------------------------------------------------
" normal mode
autocmd filetype python map<buffer> <f5> :!clear<cr>:w<cr>:!python %<cr>
autocmd filetype lua map<buffer> <f5> :!clear<cr>:w<cr>:!lua %<cr>
autocmd filetype sh map<buffer> <f5> :!clear<cr>:w<cr>:!./%<cr>
" insert mode
autocmd filetype python imap<buffer> <f5> <esc>:!clear<cr>:w<cr>:!python %<cr>
autocmd filetype lua imap<buffer> <f5> <esc>:!clear<cr>:w<cr>:!lua %<cr>
autocmd filetype sh imap<buffer> <f5> <esc>:!clear<cr>:w<cr>:!./%<cr>
"-----------------------------------------------------------
"-----------------------------------------------------------
" taglist
"-----------------------------------------------------------
let Tlist_Exit_OnlyWindow = 1
let Tlist_Use_Right_Window = 1
let Tlist_File_Fold_Auto_Close = 1
map <leader>to :Tlist<cr>
"-----------------------------------------------------------
" for quickfix
"-----------------------------------------------------------
nmap <silent> <leader>n :cn<cr>
nmap <silent> <leader>p :cp<cr>
"-----------------------------------------------------------
" for vimgdb
"-----------------------------------------------------------
source ~/vimrc/gdb_mappings.vim
"-----------------------------------------------------------
" WinManager Setting
"-----------------------------------------------------------
let g:winManagerWindowLayout = "FileExplorer"
let g:winManagerWidth = 30
let g:defaultExplorer = 0
nmap <silent> <leader>wm :WMToggle<CR>
"-----------------------------------------------------------
" for A.vim a useful plugin
"-----------------------------------------------------------
nmap <leader>aa :A<cr>
nmap <leader>as :AS<cr>
nmap <leader>av :AV<cr>
"-----------------------------------------------------------
" for MiniBufExplorer and buffer opearate
"-----------------------------------------------------------
nmap <leader>1 :b 1<CR>
nmap <leader>2 :b 2<CR>
nmap <leader>3 :b 3<CR>
nmap <leader>4 :b 4<CR>
nmap <leader>5 :b 5<CR>
nmap <leader>6 :b 6<CR>
nmap <leader>7 :b 7<CR>
nmap <leader>8 :b 8<CR>
nmap <leader>9 :b 9<CR>
nmap <leader>0 :b 10<CR>
阅读全文....
既然准备尝试在linux下开发程序,一些准备工作是必须的,比如makefile,shell,等等,目前学习了一下makefile文件的写法,的确大有学问,趁着这个学习的机会,翻看了一下公司目前的通用makefile,发现其实写的并不是很好,这点到时候和总监去说说,虽然改起来方便,但是实际上对于文件的依赖性处理的有问题。
另外,看了一下automake的东西,发现那东西只适合程序的发布时使用,不适合开发的时候使用。
于是,自己想写一个开发用的make文件自动生成工具,也有些思路,顺便熟悉一下这段时间囫囵吞枣式的语言学习,
以前就有想法,将数据结构的课程习题全部用C++,Python两种语言来完成,当时的确是水平不济,加不想用太多时间在python上。现在不一样了,其实作为一个游戏开发人员,脚本语言的掌握是很必要的:)另外,linux下的shell(bash)编程也挺有意思和用途。
所以,和那时比较,现在的野心也更大了,我决定用bash shell,C++,lua,python四种语言来实现这个适合工程用的自动make文件生成:)
希望能够顺利,这个工作不大,是锻炼语言的好机会。
阅读全文....
function PrintTable(o, f, b)
if type(f) ~= "function" and f ~= nil then
error("expected second argument %s is a function", tostring(f))
end
if type(b) ~= "boolean" and b ~= nil then
error("expected third argument %s is a boolean", tostring(b))
end
p = f or io.write
b = b or false
if type(o) == "number" or
type(o) == "function" or
type(o) == "boolean" or
type(o) == "nil" then
p(tostring(o))
elseif type(o) == "string" then
p(string.format("%q",o))
elseif type(o) == "table" then
p("{/n")
for k,v in pairs(o) do
if b then
p("[")
end
PrintTable(k, p, b)
if b then
p("]")
end
p(" = ")
PrintTable(v, p, b)
p(",/n")
end
p("}")
end
end
最近因为工作需要,学习了lua,呵呵,挺有意思了,甚至让我萌生了回去继续学习以前学过一下的python.
因为常用vim编写lua,调试不是太方便,所以根据programming in lua写了上面这个函数,用起来还算方便,当
需要输出到文件的时候就指定第二参数,或者通过io.output改变io.write的行为.第三参数是指定需要输出
到文件并能重新读出来时的[]号的,具体原因就不多讲了,看看programming in lua 就知道了.
下面是个示例:
a = {[{100, 200}] = { 300, 400}, 200, { 300, 500}, abc = "abc"}
PrintTable(a, io.write, true)
输出结果如下:
{
[1] = 200,
[2] = {
[1] = 300,
[2] = 500,
},
[{
[1] = 100,
[2] = 200,
}] = {
[1] = 300,
[2] = 400,
},
["abc"] = "abc",
}
其实还是合法的lua语句,可以用来作为序列化语句,或者配置文件.没有经过严格测试,仅作为抛砖引玉.
对于新手,提示一下,可以通过在此函数前加上module("PrintTable", package.seeall),并将此文件保存在
类似lualibs的库目录,然后就可以通过在你自己的程序中用require "PrintTable"来使用此函数了.
阅读全文....
23章:
结束处理程序:
__try{}
__finally{}块语句,能保证在运行完__try的语句后能调用__finally{}块中的语句,就算是提前的return,break,continue,goto, 内存访问违规等都可以保证,但是当调用ExitThread或ExitProcess时,将立即结束线程或进程,由于调用TerminateThread或TerminateProcess而结束线程或进程,不会执行__finally块中的代码.
但是在__try块过早退出时,会导致局部展开,影响效率,应该尽量放在外面.
当碰到一些的确需要在块内部使用return时,可以先用__leave关键字代替,以直接从__try块转到__finally,并在最后调用return语句返回,这样避免了局部展开,提高了效率,但是额外的代价是需要加入一个表示函数成功完成的bool变量.
可以在__finally块中调用AbnormalTermination内部函数确定是否是非正常退出__try块,发生局部展开和内存访问违规等都算在内,此时返回true,当自然进入__finally块时,此函数返回false.可以通过这种方式决定到底在__finally块中执行什么代码.不能在其它地方调用.
此结束处理程序的作用:
简化错误处理,提高程序可读性,使代码更容易维护,使用得当具有很小的系统开销.
24章:
异常处理程序:
__try{}
__except(){}
在__try块中使用return,break,continue,goto语句不会带来额外开销.
在
__try{}
__except(EXCEPTION_EXECUTE_HANDLER){}
发生异常时,执行完__except块中的代码后,从其后的下一条语句开始执行.
__try{}
__except(EXCEPTION_CONTINUE_EXCUTION){}
发生异常时,执行完__except块中的代码后,重新从导致异常的原指令开始执行.
__try{}
__except(EXCEPTION_CONTINUE_SEARCH){}
发生异常时,不执行__except块中的代码,直接查找上一个匹配的__except块执行.
可以在_except块中和条件中调用GetExceptionCode()函数来确定到底是什么异常,不能在其它地方调用.
当一个异常发生时,操作系统向引起异常的线程的栈里压入三个结构,
EXCEPTION_RECORD, EXCEPTION_POINTERS, CONTEXT ,其中EXCEPTION_POINTERS就是两个指针成员,指向压入栈中的其它两个成员, breakpad的exinfo结构就是这个指针的类型.并且成员和含义完全一样.
GetExceptionInformation函数只能在异常过滤器中使用,也就是__except的条件中调用.块中都不能使用.但是可以想办法在异常过滤器中就将结果保存下来,放到以后使用.
软件异常:
可以由void RaiseException(
DWORD dwExceptionCode,
DWORD dwExceptionFlags,
DWORD nNumberOfArguments,
const ULONG_PTR* lpArguments
);
引发.但是dwExceptionCode要遵循winerror.h文件中定义的一样的规则.
第二参数为是否允许异常过滤器返回EXCEPTION_CONTINUE_EXCUTION的标志位,当设为0为允许,设为EXCEPTION_NONCONTINUABLE为不允许,当不允许的时候,异常过滤器返回EXCEPTION_CONTINUE_EXCUTION时,会引发新的异常EXCEPTION_CONTINUE_EXCEPTION.
在异常的时候发生新的异常,旧的异常消息会保留在EXCEPTION_RECORD的ExceptionRecord链表中.
25章:
未处理异常和c++异常
Windows内部启动线程的方式也使用了SHE框架,当一个线程发生异常的时候,首先通过UnhandledExceptionFilter(GetExceptionInformation())处理,默认方式为弹出熟悉的报错对话框,按close后通过ExitProcess(GetExceptionCode())退出,按debug即传递合适的参数CreateProcess开启新的调试进程来调试异常的程序.
通过以SEM_NOGPFAULTERRORBOX为参数调用SetErrorModel函数,可以防止显示异常消息框.通过对每个线程和主线程的try-except块包装,可以自己处理每一个异常.而不调用默认的UnhandledExceptionFilter.windows还提供SetUnhandledExceptionFilter函数来定义某个进程中所有的线程发生异常时调用的异常过滤器.此函数的参数为用户自定义的异常过滤器的指针.
在VC中,C++的异常实际用SHE来实现,并且SHE比C++异常有更多功能,比如可以从一个硬件错误中恢复过来.可以在一个程序不同函数中同时使用两套异常系统,但是不能混合使用,也不能在一个函数中使用两套系统.
阅读全文....