CString 的 Bug(MFC42)

前两天在处理一个字符串的时候发现一个奇怪的现象:当删除字符串中的引号时,后面的中文都变成了乱码,搞得我一头雾水。

一看内存,发现中文字符的前后两个字节被分了家:一个字节岿然不动,一个字节根据删除减少的字符数向前移动。

这就奇怪了,难道是MFC的问题??

跟进去一看,果不其然! MFC42 (vs6)是这么处理的:


CString::Remove(TCHAR ch)

......

 while (pstrSource < pstrEnd)
 {
  if (*pstrSource != chRemove)
  {
   *pstrDest = *pstrSource;
   pstrDest = _tcsinc(pstrDest);
  }
  pstrSource = _tcsinc(pstrSource);
 }

MFC42其实考虑到了MBCS的情况, 所以用了 _tcsinc来判断下一字符的位置;可惜只考虑了一半,赋值时

*pstrDest = *pstrSource

可不像它想象的那么聪明,只能根据类型定义拷贝了单个字节。 所以就发生了删除一个字符后,后面的字符往前移动时只移动了双字节字符的前一个字节的情况。

根据源代码的意思,实际上删除任何一个字符,其后面的中文字符串都会乱掉。

字符串的处理是个蛮古董的话题了,出现这样子的bug确实让我吃了一惊。刚好手头还有vs2003, 于是试了试,发现已经更改过来了。

代码如下:

  while( pszSource < pszEnd )
  {
   PXSTR pszNewSource = StringTraits::CharNext( pszSource );
   if( *pszSource != chRemove )
   {
    // Copy the source to the destination.  Remember to copy all bytes of an MBCS character
    PXSTR pszNewDest = pszDest+(pszNewSource-pszSource);
    while( pszDest != pszNewDest )
    {
     *pszDest = *pszSource;
     pszSource++;
     pszDest++;
    }
   }
   pszSource = pszNewSource;
  }

可以看到MFC(7.1)特地用了一个while循环来处理多字节字符的情况。这次,MFC(7.1)记起来了,还在代码里加了注释。它说:

“Remember to copy all bytes of an MBCS character”

我想看看msdn上对于这个bug的说法, 于是google了一把 “CString Remove Bug Site:microsoft.com”。

这一Google没发现Remove的说明, 却又发现了Right, Left, Mid的bug说明:

KB810448:FIX: CString Functions Right, Left, and Mid May Cause Access Violation.

文章最后说明,该bug存在于MFC42(visul studio 6), Visual C++ .NET 2002 Standard Edition中。

有了前次的经历,Right, Left, Mid在MFC42中有问题就不那么吓人乐,不过在vs2002中还存在,就有点......

由于没找到关于 CString::Remove 的 bug说明,因此写了这篇文章,提醒还在使用 vs2003之前版本的朋友们,慎用 CString 的 Remove, Right, Left, Mid。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值