Bill's profileBinary boy's lifePhotosBlogLists Tools Help

Blog


    4/23/2009

    VC中创建线程分析

    文章作者:Bill Xie   自由转载,但请注明作者和原始出处!
    ================================
    1、CreateThread、_beginthreadex、AfxBeginThread的区别和正确使用:
     
    CreateThread是一个Windows 的API函数,_beginthreadex是一个微软VC中C运行时库中的线程创建函数,AfxBeginThread则是MFC中的线程创建函数。
    其依赖关系为:<--表示被依赖
     
    CreateThread <--_beginthreadex
    CreateThread <-- AfxBeginThread
     
    _beginthreadex为每个使用线程在Heap上创建(用__calloc_crt,相当于calloc)了一个tiddata结构并且设定到动态TLS。这样C运行时库中使用静态变量的几个函数就可以得到只和线程相关的一份“静态”和“全局”变量了,C运行时全局变量也不会互相干扰。假若使用CreateThread创建了这同样的线程,因为没有事先分配这个tiddata结构,那么后果自然就很严重了。
     
    但是使用了_beginthreadex也有一个不算麻烦的小麻烦。
     
    线程最好的退出方式是从return退出,所有的资源都会正确的释放,如果调用ExitThread退出线程,那么线程堆栈上的内容被自动清除,但是C++对象不能够通过调用析构函数而正确的清除。而和_beginthreadex对应的_endthreadex恰恰就是调用了ExitThread来终止线程。所以,这下_endthreadex也不能调用了。那么在前面分配的tiddata怎么办?没有任何办法,除非去调用_endthreadex才会得到释放,但是ExitThread语句又紧跟在后边。还好,tiddata结构非常小,不超过100个字节,但是要是遇上傻大黑粗的野蛮程序员,在进程生命期中反复创建线程,也挺恐怖。
     
    所以最好的做法就是,在线程中,避免使用C运行时函数,用C++运行时库或者Windows API解决问题。这样就可以避免使用_beginthreadex,而用CreateThread创建线程,也不会有tiddata结构的运行时内存泄漏了。(或者,不在线程中使用C++对象,这样就不怕_endthreadex的ExitThread 了。 吐舌 馊主意!不过_beginthreadex本来就是为使用C函数的线程准备的。)
     
    至于AfxBeginThread,是MFC中定义的一个函数,如果你使用MFC框架,那么应该使用这个函数,这样更符合框架的设计目的。这个函数内部的实现就是通过CreateThread,因为既然都使用MFC了,还费劲使用C函数库干嘛?
     
     
    2、CreateThread的不知道算不算Bug的Bug:
     
    CreateThread的定义请参见不同版本的MSDN。
     
    该API函数的第2个参数 dwStackSize 以及 第5个参数 dwCreationFlag 分别指定了线程堆栈的大小和创建标志。
     
    按照文档中的说明,dwCreationFlag有一个设定值为STACK_SIZE_PARAM_IS_A_RESERVATION。这个标志的含义是,将指定大小的堆栈在虚拟内存中分配,并且初始只映射系统缺省页数的物理内存(大概是两个页),随着堆栈使用的增大,系统根据堆栈物理内存页后方的设定为PAGE_GUARD属性的页触发来把更多的物理内存映射到后续的页。
     
    值得注意的是,STACK_SIZE_PARAM_IS_A_RESERVATION这个标志只在Windows XP以及Windows 2003以及更新的系统上才会得到支持。如果没有设定这个标志,并且也让线程一创建就开始运行(大部分时候是这样),那么系统会参照dwStackSize中指定的堆栈大小,并参照内存分配最小粒度以及页对齐原则,把一定大小的物理内存映射给堆栈。
     
    看上去一切都很不错,但是如果你尝试创建一个会很快耗光堆栈的线程ThreadProc,并且用下面的语句创建:
    CreateThread(NULL, 1024 * 1024 /* 1MB */, ThreadProc, NULL, 0, &threadId);
    然后在线程中精心设置好异常捕捉,满心欢喜的等待EXCEPTION_STACK_OVERFLOW的到来。
    那么你会震惊的发现:
     
    程序因为EXCEPTION_ACCESS_VIOLATION异常而直接退出了。没有EXCEPTION_STACK_OVERFLOW。
     
    你重新设置异常条件,决定捕捉全部的异常,但是你会发现你完全无法捕捉。Why?
     
    接下来,你把堆栈大小设置为:1024 * 1024 + 1 或者1024 * 1024 - 8092,那么又可以准确的捕捉到溢出异常了。
    或者你把dwStackSize设置为0,或者给dwCreationFlag 加上STACK_SIZE_PARAM_IS_A_RESERVATION标志,也可以成功捕捉异常。
     
    现在应该知道原因了。运行在x86上的Windows XP,目前内存分配最小粒度为64KB,用户态下页面大小是4KB。
     
    当把dwStackSize设置为0时,系统会缺省设置堆栈为1MB大小,但是事实上线程得不到1MB的堆栈,因为系统会在堆栈最后的部分用加上PAGE_GUARD属性的页来检测溢出,并且还要保留用于处理溢出异常发生时的页面,所以可以检测到异常。
     
    而给dwCreationFlag 加上STACK_SIZE_PARAM_IS_A_RESERVATION标志时,按照64KB分配粒度的原则,堆栈最后的部分始终有足够的页来检测溢出和处理异常。所以也很安全。
     
    而为线程指定1024 * 1024大小堆栈时,堆栈边界正好和64KB以及1MB边界对齐的,当完全提交物理内存时,堆栈的所有页的属性都将是PAGE_READWRITE(事实上应该是一个Windows的Bug,但是考虑性能原因而故意让其存在)。所以系统根本没机会检测到溢出错误,而会在堆栈溢出后直接引发EXCEPTION_ACCESS_VIOLATION。而因为没有预留的异常处理页面,异常处理程序又会引发一个EXCEPTION_ACCESS_VIOLATION异常。天啦!!整个进程就这样崩溃了。吐舌
     
    而为什么指定1024 * 1024 + 1 或者1024 * 1024 - 8092就可以捕捉异常了呢?因为堆栈大小在超过1MB后,是按照1MB对齐原则,哪怕多一个字节,系统也会多映射1MB的物理内存。这样足够两页的异常检测和异常处理页面。1024 * 1024 - 8092大小正是这个原因所以能正确引发异常。
     
    所以,正确的做法是,如果想在运行CreateThread时指定堆栈大小,并且全部提交物理内存的话,那么大小必须保证在整1MB边界上留出至少两个页面给系统。
    4/14/2009

    Windows XP用户不必担心,XP安全更新支持将延续至2014年

    本来没打算更新在Blog上,但是我在techweb上对其颠倒黑白的“谣言”进行了如同下文的回复。结果,丧心病狂的编辑居然给我删除了。显然,这是那个谣言是收了国内某些“安全厂商”的钱而制造出来的。发在自己的Blog上,希望能有更多人从Google上搜索到,也有点立此存照的含义。  尴尬

    快一年没更新Blog了,没准借这个机会又开始更新了。  ^_^

    2009年4月14日,是微软Windows XP Mainstream Supoort到期的时间。江湖传闻,微软将不会再为XP进行安全更新,而XP也将变得更不安全。

    事实上,这完全是错误的!

    ========================
    微软的两种支持策略分别为:

    1、Mainstram support针对免费和付费支持,包括免费安全升级和Bug修正,适用于所有购买Windows XP零售版本的用户。Mainstream support将延续至2009年4月。

    2、Extended support主要针对所有Windows用户提供免费安全升级,Extended support将持续到2014年4月。新的Bug修正需要通过Extended Hotfix Support程序来实现。
    ========================

    Windows XP的用户可以放心使用XP直到2014年4月8日。

    参考链接:Microsoft Support Lifecycle (Windows XP Family)

    http://support.microsoft.com/lifecycle/?LN=en-gb&x=16&y=12&C2=1173

    5/6/2008

    IE6:玻璃一样脆

    5月以来,似乎开始流行起了一种新的病毒,因为其症状,有些网站上称之为“机器狗”。但经过整整一天和病毒搏斗之后,感觉这种病毒并非简单的是“机器狗”,而是一种利用了最新的IE6漏洞的新病毒。

     

    一、感染:

    感染这种病毒非常容易,只需要用IE6浏览带有该病毒的网站。即便将IE6的Internet安全设置为“中”、禁用Remote Registry等服务后、并且用升级到最新数据的Norton杀毒软件监控着、在活动目录网络中并且禁止了来宾帐户,也是立即就会被感染。

    很显然,这是利用IE6某个MIME运行方面的漏洞,或者FSO或者WSH的某个漏洞,这样一个漏洞可以让IE6在当前用户权限下没有任何提示的下载并运行指定的数据(缓冲区溢出?)。 

     

    二、运行:

    该病毒一旦被下载和运行,会在X:\Windows\system32\drivers 写入病毒文件,以便在计算机下次启动的时候,病毒会以驱动级别加载。而且非常可怕的是,目前瑞星、诺顿的最新版本都不将这些文件识别为病毒文件。

    接下来,病毒会修改:X:\Windows\system32\下的(参考自瑞星卡卡论坛:http://bbs.ikaka.com/showtopic-8501837.aspx

    services.exe
    cdfview.dll
    cards.dll
    lsass.exe
    mfc40u.exe

    这几个文件。为了进一步加强反查杀能力,病毒会不停的在X:\Windows以及X:\Program Files下生成按数字顺序命名的病毒可执行文件,然后在

    Software\Microsoft\Windows\CurrentVersion\Run

    下指定自动加载这些病毒文件。而且这些病毒文件运行后还会分别写日志。  (sweat) 汗

    做完这些仍然不尽兴,你会在X:\Windows\System32 下会发现一大堆随机命名的dll文件。

    重重严密设置机关后,病毒其实想干的事情也不过就两件:1、盗盗你的QQ密码、网游密码等等;2、时不时给你弹出一个“很傻很无聊”的网页。  (sweat) 汗(sweat) 汗(sweat) 汗

     

    三、清除:

    如果你能忍受密码被盗,或者甚至想好奇看看会不会有“很黄很暴力”的网页,就别看下面了,并且请继续坚持使用IE6吧。

    清除这个病毒其实很简单,但是比较麻烦的一点是需要一个不用启动WinXP就可以完全访问硬盘的环境。目前有很多可以以提示符状态访问NTFS分区的工具,最简单的就是利用WinXP的紧急恢复盘。我的机器上同时装了一个测试用的Vista,所以事情就更简单了。

    在开始清理之前,请先到http://bbs.ikaka.com/showtopic-8501837.aspx或者其他网站下载被修改的5个系统文件的无毒版本。然后加载硬盘访问环境,按照以下的顺序执行清理:

    1、进入X:\Windows\System32\Drivers 下,找到更新时间最新(和本次计算机启动时间相差不超过一天)的几个sys文件(注意!这些文件都是同时具有系统和隐藏属性!)删除之;

    2、进入X:\Windows\System32 下,找到更新时间最新的dll,cdf文件,删除之;

    3、进入X:\Windows\System32 下,备份被病毒感染的5个系统文件(便于替换失败时改回),用无毒版本替换之;

    4、进入X:\Windows 下,找到最新更新时间的exe,log文件,删除之;

    5、进入X:\Program Files 下,找到最新更新时间的exe文件,删除之;

    6、重启动WinXP到安全模式下,运行msconfig,将其中和X:\Windows以及X:\Program Files目录下可执行文件同名的加载项选除。之后运行gpedit.msc,在“本地计算机策略→计算机配置→管理模板→系统”中关闭Windows的文件保护

    7、正常启动WinXP,如果正常启动,则万事大吉。如果启动失败,证明替换的系统文件版本不正确,那么带毒启动,或者在别的机器上查找到正确的版本后,重复1-7的步骤。

     

    四、结论:

    这是一个目前IE6完全无法防范的病毒,而且主流的杀毒软件也检查不了病毒的核心文件。只要正在使用IE6,那么目前没有任何办法防范被感染。在微软没有给出新补丁之前,你只要浏览网站,就随时可能中毒,如同在乌干达泡妞却忘了带套套一样。  (cry) 大哭

    所以,在微软给出新补丁之前,暂时使用速度缓慢的IE7或者兼容性不够好的FireFox吧。  (sy) 害羞

    2/1/2006

    Yahoo助手以及CNNIC插件惊魂----有惊无险

    今天因为要看一下以前的老代码,懒得打开巨大无比的VS Studio,于是去下载了一个最新版本的UltraEdit。也许是看英文看怕了,鬼使神差之下,在华军下载了一个简体中文汉化版本。
     
     
    越是甜的馅饼越是有着可怕的阴谋,这不,Yahoo助手和CNNIC中文插件就这么不请自到,来到了我的计算机上。
     
     
    眼看悲剧就要发生,但是因为二进制平时的一贯小心,用最新版本的Anti Spyware成功阻止和清除了这两个垃圾。 
     
    记住下面的话吧:
     
    将你的计算机上安装上sp2,打开Auto Update;
    安装MS Anti Spyware,打开Auto Update;
    打开系统文件保护以及打开每一个磁盘卷上的系统还原。
     
    Yahoo助手(3721的一种诈尸方式)以及CNNIC插件已经通过收买方式进入了很多自由或者共享软件,还是时刻小心为好。
    1/25/2006

    FW: Google Agrees to Censor Results in China

    Online search engine leader Google Inc. has agreed to censor its results in China, adhering to the country's free-speech restrictions in return for better access in the Internet's fastest growing market.

    The Mountain View, Calif.-based company planned to roll out a new version of its search engine bearing China's Web suffix ".cn," on Wednesday. A Chinese-language version of Google's search engine has previously been available through the company's dot-com address in the United States.

    .......................

    Yahoo came under fire last year after it provided the government with the e-mail account information of a Chinese journalist who was later convicted for violating state secrecy laws.

    Initially, Google's Chinese service will be limited to searching Web pages and images. The company also will provide local search results and a special edition of its news service that will be confined to government-sanctioned media.

     

    (Full Story)

    1/23/2006

    莫尔斯电码表(Morse Code)以及通信发音

    字母和数字

     

    A   .-           Q   --.-            1   .----
    B   -...         R    .-.             2   ..---
    C   -.-.         S    ...             3   ...--
    D   -..          T     -              4   ....-
    E    .            U    ..-             5   .....
    F   ..-.          V   ...-             6   -....
    G   --.          W   .--             7   --...
    H   ....         X   -..-             8   ---..
    I    ..           Y   -.--             9   ----.
    J   .---         Z   --..             0   -----
    K    -.-         
    L   .-..         
    M    --          
    N    -.          
    O   ---          
    P   .--.         

     

    标点符号

     

    ?问号      ..--..  /      斜线     -..-.
    (左括号   -.--.  )     右括号   -.--.-
    ——破折号 -....-        .句号     .-.-.-
    ,逗号      --..--        ;分号     -.-.-.
    :冒号      ---...        改错符号   ......
    “”引号      .-..-.        =等号      -...-
    `             .----.        @          .--.-.


    注:
        点为短声,划为长声,一个长声的长度等于3个短声。点划之间的间隔长度等于一个点;字母
    和字母之间的间隔长度为3个点;字和字之间的间隔长度为5个点。

     

    通信发音
     
    A = Alpha     M = Mike          Y = Yankee
    B = Bravo     N = November   Z = Zulu
    C = Charlie   O = Oscar          1 = Unaone
    D = Delta     P = Papa           2 = Bissotwo
    E = Echo      Q = Quebec       3 = Terrathree
    F = Foxtrot  R = Romeo       4 = Kartefour
    G = Golf       S = Sierra         5 = Pantafive
    H = Hotel    T = Tango         6 = Soxisix
    I = India     U = Uniform       7 = Setteseven
    J = Juliet    V = Victor          8 = Oktoeight
    K = Kilo      W = Whiskey      9 = Novenine
    L = Lima     X = X-ray           0 = Nadazero

    8/25/2005

    Google Talk

    今天和Wanz、姚姚测试了一下Google Talk的voip功能。声音效果很不错,非常稳定和“强劲”,几乎没有延迟,毕竟是主要用于语音的IM。
     
    有兴趣的XDJM请上 talk.google.com
     
    如果需要邀请,请留下你的电子邮件。 
     
    PS: Google Talk用的语音模块和Skype一样,都是Globla Ip Sound的,但是Skype除了语音就没别的了。而Google呢?Talk只是一个开始,搜索、地图加GMail,已经有足够多的想象空间了。