??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲第一在线,久久成人精品一区二区三区,欧美日韩在线电影http://www.shnenglu.com/sigepluto/category/7799.htmlC++夜未?/description>zh-cnSun, 28 Mar 2010 06:03:26 GMTSun, 28 Mar 2010 06:03:26 GMT60MFC中一个危险的Bughttp://www.shnenglu.com/sigepluto/archive/2010/03/26/110622.htmlJakcieJakcieFri, 26 Mar 2010 14:15:00 GMThttp://www.shnenglu.com/sigepluto/archive/2010/03/26/110622.htmlhttp://www.shnenglu.com/sigepluto/comments/110622.htmlhttp://www.shnenglu.com/sigepluto/archive/2010/03/26/110622.html#Feedback3http://www.shnenglu.com/sigepluto/comments/commentRss/110622.htmlhttp://www.shnenglu.com/sigepluto/services/trackbacks/110622.html 

上次说日本v啸警报的时候,E序出错。在解析代码的时候,发现了MFC中的一个Bug?/p>

一。问题的产生?/p>

q个E序Q用来处理日本各U天气预报数据,包括灑֮的预报。如果地震,台风之类的自然灾宛_来,E序会把预报数据q行处理Q生成相应的警报信息Qƈ在电视上面显C滚动的字幕来提C。程序本w,是几q前公司的其他h写的。里面有涉及到文件读写的地方Q有很多地方Q用了MFC中自带的文gdcCStdioFile?/p>

CStdioFileq个文gdc,估计大家都不陌生。这个类的父c,是CFilecRCStdioFilecLw的功能也很单。CStdioFilecL一个成员函数是ReadStringQ函数的定义如下Q?/p>

    virtual LPTSTR ReadString(__out_ecount_z(nMax) LPTSTR lpsz, __in UINT nMax);
    virtual BOOL ReadString(CString& rString);
MSDN定义如下http://msdn.microsoft.com/library/x5t0zfyf(VS.80).aspxQ?pre style="border-bottom: #cecece 1px solid; border-left: #cecece 1px solid; padding-bottom: 5px; background-color: #fbfbfb; min-height: 40px; padding-left: 5px; width: 650px; padding-right: 5px; height: 118px; overflow: auto; border-top: #cecece 1px solid; border-right: #cecece 1px solid; padding-top: 5px">
BOOL ReadString(CString& rString);
throw( CFileException );
Return Value
A pointer to the buffer containing the text data. NULL if end-of-file was reached without reading any data; or if boolean, FALSE if end-of-file was reached without reading any data.

ReadString函数能直接读取文本中的一行数据到CString中,很方ѝ读到文件结,没有dM数据的时候,q回FALSE。很单的函数Q但恰恰是这个函数有Bug?/p>

E序在处理数据的时候,会生成一些时文Ӟ然后会读取这些时文件中的数据,d操作Q正是用的CStdioFile的ReadString函数。读取流E很单:

while(dFile.ReadString(Str_temp))
{
    doSomething();
}

当时的现象ؓQ读取到最后一行,L直接q回FALSEQ怎么也读不出最后一行来。看了看文g的最后一行,包含2176个字W的数据Q没有换行符。没有Q何异常啊。当时没惛_是MFC的BugQ因Z前有q样那样的毛病,多数是预报数据本w有问题Q所以这ơ也是先分析数据了。分析来分析去,没发现这ơ的数据有什么异常。后来发现如果最后一行的文g不是2176个字W,p正常d来。奇了怪了Q?176也不是什么特D长度啊。实验了几次后,觉的是在不对劌Ӏ莫非是MFC的BugQ?/p>

二。发现问题所?/p>

军_看看MFC的代码再说。做了个单的试E序Q跟到MFC代码里一看,果然是MFC的问题!试代码如下Q?/p>

    CStdioFile  dFile;
    dFile.Open("text.txt",CFile::modeRead);
    CString str;
    while (dFile.ReadString(str) != FALSE )
    {
        printf("%s", str);
    }
    dFile.Close();

试代码很简单,读text.txt文g中的每一行,然后打印出来。还?176个字W就不行。确定了不是数据的问题,是MFC代码本n的Bug?/p>

MFC的ReadString代码如下Q(中文是我加的注释Q?/p>

BOOL CStdioFile::ReadString(CString& rString)
{
    ASSERT_VALID(this);
    rString = &afxChNil;    // empty string without deallocating
    const int nMaxSize = 128;  //临时字符串的长度
    LPTSTR lpsz = rString.GetBuffer(nMaxSize);  //保存每次d到的字符串到CString?/span>
    LPTSTR lpszResult;  //指向每次d的字W串
    int nLen = 0;
    for (;;)
    {
        lpszResult = _fgetts(lpsz, nMaxSize+1, m_pStream); //d操作
        rString.ReleaseBuffer();
        // handle error/eof case
        if (lpszResult == NULL && !feof(m_pStream))
        {
            clearerr(m_pStream);
            AfxThrowFileException(CFileException::generic, _doserrno,
                m_strFileName);
        }
        // if string is read completely or EOF
        if (lpszResult == NULL ||
            (nLen = lstrlen(lpsz)) < nMaxSize ||
            lpsz[nLen-1] == '\n')
            break;
        nLen = rString.GetLength();
        lpsz = rString.GetBuffer(nMaxSize + nLen) + nLen; //位置后移
    }
    // remove '\n' from end of string if present
    lpsz = rString.GetBuffer(0);
    nLen = rString.GetLength();
    if (nLen != 0 && lpsz[nLen-1] == '\n') // 最后结果中Q去掉回车符
        rString.GetBufferSetLength(nLen-1); 
    return lpszResult != NULL;  // q里是Bug的关键。返回g对!
}

可以看到QReadString的底层,是用fgets来读取文件的。在内部Q每ơ读?28个字W到CString中,然后位置后移Q反复读?28个字W,直到遇到回RW或者文件结束。最后把回RW去掉,q回一个CString。其中,lpszResult也指向每ơ读出的字符丌Ӏ?/p>

q里q出问题所在了Q?176个字W,正好?28?7倍!也就是说Q?font color="#ff0000">只要文g最后一行是128倍数个字W,׃定会q回FALSE?/strong>

Z么会q样呢,因ؓReadString在每ơ读?28个字W的时候,用lpszResult指向d到的字符丌Ӏ如果读满了128个字W,ql读Q如果读到的字符不够128个,那么q束读取?/font>

当一行数据正好ؓ128的倍数Q又没有回RW的时候,会发生什么呢Q比如最后一行数据是128个,那么Q读一?28个字W,会l读下一ơ,但是下一ơ的dQ什么也没有dQlpszResult指向NULLQ最后的q回|是return lpszResult != NULL; 所以返回FALSE?/font>

但之前读到的128个字W,已经在CString里面了?/font>也就是说实际上读取已l成功了Q但q是q回了FALSE。返回g恰当Q?/font>

Bug的描qͼ当文件的最后一行数据,正好?28的倍数个字W的时候,?/font>ReadStringdQ一定会q回FALSE。但实际上读取是成功的,q回的CString中的数据是正的Q(VC6.0中存在这个BugQVS2005中,没有q个BugQ?/font>

q个BugQ只会媄响到最后一行数据。因为如果有换行W的存在QlpszResult׃会ؓNULL?/font>

三。解x?/font>

要解册个问题,也简单,修改一下判断ReadString成功与否的语句:

while (dFile.ReadString(str) != FALSE || str.GetLength() != 0)

在返回FALSE的情况下QCString的长度不?Q就不算dp|。或者这?

if(!dFile.ReadString(str) && str.GetLength() == 0)

在返回FALSEq且CString的长度ؓ0Q则读取失败,否则是d成功?/p>

q个E序Q是用VC6.0做的Q我有看了看VC2005中的代码Q发现这个Bug被修复了Q代码如下:

BOOL CStdioFile::ReadString(CString& rString)
{
    ASSERT_VALID(this);
    rString = _T("");    // empty string without deallocating
    const int nMaxSize = 128;
    LPTSTR lpsz = rString.GetBuffer(nMaxSize);
    LPTSTR lpszResult;
    int nLen = 0;
    for (;;)
    {
        lpszResult = _fgetts(lpsz, nMaxSize+1, m_pStream);
        rString.ReleaseBuffer();
        // handle error/eof case
        if (lpszResult == NULL && !feof(m_pStream))
        {
            Afx_clearerr_s(m_pStream);
            AfxThrowFileException(CFileException::genericException, _doserrno,
                m_strFileName);
        }
        // if string is read completely or EOF
        if (lpszResult == NULL ||
            (nLen = (int)lstrlen(lpsz)) < nMaxSize ||
            lpsz[nLen-1] == '\n')
            break;
        nLen = rString.GetLength();
        lpsz = rString.GetBuffer(nMaxSize + nLen) + nLen;
    }
    // remove '\n' from end of string if present
    lpsz = rString.GetBuffer(0);
    nLen = rString.GetLength();
    if (nLen != 0 && lpsz[nLen-1] == '\n')
        rString.GetBufferSetLength(nLen-1);
    return nLen != 0; //q回值变了!
}

我们看到QVC2005中,d部分的代码与VC6.0中的代码完全一栗不一L地方只是q回值的部分。VC2005的ReadString中,q回gؓ

return nLen != 0;

也就是说Q只要读出的CString的长度不?׃ؓd成功。与我修改后的方法完全一致。就q样向客戯释,然后修改了。悲剧的是,几年前所有程序中所有用ReadString函数的地方,都要q行修改。。?/p>

MFC的这个Bug比较隐蔽Q^怸Ҏ发现Q但一旦遇到特D长度的数据Q就会表现异常。所以,在用VC6.0开发的时候,量避免使用ReadStringQ或者在使用中,多判断一步读取出来的CString长度。避开q个Bug?/p>

Jakcie 2010-03-26 22:15 发表评论
]]>
虚惊一场的啸http://www.shnenglu.com/sigepluto/archive/2010/03/08/109161.htmlJakcieJakcieSun, 07 Mar 2010 18:07:00 GMThttp://www.shnenglu.com/sigepluto/archive/2010/03/08/109161.htmlhttp://www.shnenglu.com/sigepluto/comments/109161.htmlhttp://www.shnenglu.com/sigepluto/archive/2010/03/08/109161.html#Feedback1http://www.shnenglu.com/sigepluto/comments/commentRss/109161.htmlhttp://www.shnenglu.com/sigepluto/services/trackbacks/109161.html2?7日,智利发生8.8U特大地震,1个世U以来最强的地震Q全球都在关注。其中,日本的反应尤其大。日本本w自然灾害特别多。火山,地震Qv啸,以及z水。所以,对这U自然灾宛_然的比较敏感。最主要的原因,在于智利的地震,会媄响到日本Q这是有前R之鉴的?/p>

1960q智利v域发生了9.5U(太恐怖了。。。)地震。引起了啸Q一直穿q整个太qxQ从南美Q一直到东亚。日本,夏威P菲律N?00多hM。所以,q次8.8U地震,如果再来一ơv啸,那可不得了啊。这ơ智利爆发的地震Q引发了剧烈的v啸。如今,啸的巨正在横q太qxQ直奔日本v岸而来。估计到达日本时Q浪高依然可以达?0-20英尺?/p>

日本全国都在紧急动员防范v啸,电视台在电视屏幕一角实时展CZq日本地图,所有专安会遭到啸袭击的地区都被标记出来,如今Q从北v?到冲lI整个日本东v岸几乎都变成了一片红艌Ӏ屏q上方则在滚动播出沿各地发布的遉K通知Q例如,青森县已l有一万九千多戯要求dq入公用遉K?施。日本全国到现在为止已有40万hd家园。整个流E顺畅,井然有序。这一切,一斚w反映了日本在自然灑֮面前的准备工作,另一斚w也反映了日本?间的恐惧?/p>

q播员在不断在播报各地vq面的增高情况,镜头不时切换到沿岸各圎ͼ报道当地状况和抢险准备的情况Q很多沿公路如东名高速公路已l关闭,h公园停止营业Q船舶纷U入避难\Uѝ经常有dx断播韛_的播报,紧急通报某地^面出现异常增高。{眼间有了一U陷入某场战争的感觉?/p>

发个图,看的比较清楚。整个日本靠太^z的一边,全部是v啸警报?/p>

公司做的目Q正好是l各个电视台做的天气预报目Q地震台风v啸的预报Q也包含在内。关键时刻,日本电视台打电话_预报图显C的有误Q只能看到大阪的高Q其他地Ҏ有浪高。导致只能显C部分的警报图。东京电视台也打电话说电视上滚动昄的警报文字,用我们的E序处理不了Q显C出不来。马上ؕ套了Q当天公司几个h都通宵在处理。最后强制显C全国的警报图?/p>

最后发玎ͼ日本电视台预报图昄有误Q其实是正确的,本来其他地方没有浪高。ؓ什么呢Q因为根本就没那么大的浪Q?/p>

日本气象厅在3??0?5分全面解除太qx沿岸啸警报?
气象厅负责地震v啸检的N在记者会见中谢罪Uͼ“对于啸预测大大过了实际情况,以及警报旉q长表示歉意?#8221;

 

Z么这ơ的地震Q没有引起很大的啸呢?

智利此次地震所引发的v怹h很强的方向性,英国威尔士大学新港学院(University of Wales, NewportQ的Simon Haslett ?#8220;q回的v啔R常有方向性,而不是U均匀向四周传播的‘往池塘里扔矛_’似的波浪”。他表示震中最q的岸Q以及胡安费南h岛QJuan Fernandez IslandsQv啔R常强Q但是其他方向的啸能量和高度迅速减退?

而且Q地震震源的相对深度?5公里—可能也减小了v床的上升Q而正是v床的上升排挤了v水。英国u敦大学学院Bill McGuire表示“相比?004q的印度z地震,智利地震要更深,释放到地表的能量也更?#8221;?

虚惊一场啊?

至于东京电视台的预报文字处理不出来,l过我一步步DebugQ最后发玎ͼ是MFC的一个Bug造成的!气死我了。导致所有代码涉及这个Bug的地斚w要修攏V下日志,详细说说q个Bug?/p>

Jakcie 2010-03-08 02:07 发表评论
]]>
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
      <noscript id="pjuwb"></noscript>
            <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
              <dd id="pjuwb"></dd>
              <abbr id="pjuwb"></abbr>
              þþƷ99Ʒ| һպŷ| ŷ| ŷۺϵһҳ| ߹ۿһƬ| ŷһ| ŷձ| ŷһƬþþþþþ| þùƷһҳ| պĻ| ŷձmm| Ʒ| þӰԺҹƬһ| һƵ| ŷ߹ۿ| 㽶˾þð| ŷӰԺþþ| Ļ| ҹ91| ޹Ʒһ| ˳ëƬ߲| ŷպۺһ߹ۿ | ŷպһ| 㽶þһ޶ӰԺ | ŷպƷһ | ŷպĻۺƵ| þüۺ| ŷպӰԺ| avһ| Ʒŷպþ| ޵һ| պŷһ| ޾Ʒϵ| ӰȷþþƷ| һƵƷ| ޹պŷͼƬ| ۺϹ| ĵӰ| ŷƷһƷ| þþƷҳ| ƷպƷ| ޾ƷĻ| ؼؼŷһ | ޼ַ| һպƷŷƷ| 999޹| ޺ձĻ| Ƶ߿| һƵվ| ѿav| ŷպһ߹ۿ | ƷëƬ| ƵƷ| ɫavվ| þþ999Ʒ| ҹһƵ߹ۿ| ŷպСƵ߹ۿ| ޹91Ʒ| ޵һۺ| ëƬػƾþþþþ| Ůþ| ˾þô߽avԱ| ŷһƬ߲| þۺ| һƵ߿| þҹɫƷav| ŮѹڿƵþӰԺ | һ999| ޹| Ƶպ| ޹պŷ߶| 91þҹ| ŷƷ| һ߹ۿƵ | һ߲| þþƵ߾þ߿| þþþһ| ޵һƵ| ŷղһ߹ۿ | Ʒ99þò| ŷպ| һĦ߹ۿ| þþžre6оƷ| ޳| ŷvavaۺ| ޹պ| ŷպ| Ʒavٸһ| ŷԴ| Ƶվ߹ۿ| þþƷŷƬװ| Ƶһ| ŷպƷ| ŷ91| ޿Ƭ| þ߾Ʒ| ۺ| ޵һۺվ| ŷպۺϾƷ| þþƷƷۺ| ޼| þۺ99re88þð| һɫþ88ۺ88| Ʒۺ| ŷҳ| 㽶˾þð | ҹƷþһţӰ| ޵һƵ| ŷպƵһ| Ѿþ99Ʒ| ŷպ| һav˾þۺ| þ97 | ߹պ| Ʒ޲a| ŷƬ| þþƷƵ߿| avһػ| ޴Ů| þþþþùƷһ| һ| 99Ʒ99| ޾Ʒɫ| ߹ۿƵŷ| ղŷaһ| ŷ͵һ| ŷƷһ| ŷӰԺ| Ůþ99| ѼëƬһ| ѹۿwwwƵ| þȫƵ| ŷһһ| ҹӰԺ| ҹƷ17c| պƵ߹ۿ| һ| ޼ӰĻ| ޹Ʒva| ˾þþô߽ۺֱ| ɫƵһ| պŷƷһ| ŷһྫƷ| ƷƬѹۿ| ŷɫۺ| ƷŮþþ | ҹһ| ȷӰԺ| þ99߹ۿ| þѾƷձþĻ| þþþùƷһ| þóۺ| þۺ| ŷ龫Ʒþþþþӡ | ŷ1112Сxxxx| ޳ɫwww8888| ޹պŷ99| ѹۿ߹ۿ | ޹˾þ| Ѳ| ŷƵ߹ۿһ| һþþ| Ӱ| þԴƵ| ŷƷһ߲ | Ʒ| ˾޴ƷŷһСƵ | һƷ߹ۿ| ŷһ| þüһ| ŷպһƬ߹ۿ| Ʒÿոַ߲| ۺɫ| 99һ| ŷһ˾| þþƷһ| ޼1| һպ| avһaƬþ| Ʒþþþ9999ҩ| ͵ƵƵۺ| ޾Ʒһ| þѸƵ| av| þҰսav| պƵһ| ձƵ| þֻоƷƵҳ| ѾƵ| þþþþþۺɫһ| Ʒ| ޴վ| ŷջƵ| ޾ƷĻר| þþþƷѹۿͬѧ| ŷƵһ߹ۿ | ŷպŷһ| | ŷۺ| ޾ƷպƷ|