今天帮同学调试代码,发现了一个很奇怪的问题.他在资源中定义了一个字符串 IDS_USER_COUNT "Users: %d"在其函数中,他这样使用:int count = 0;
......
//count被赋值
......CString sRes;
sRes.LoadString(IDS_USER_COUNT);
sRes.Format(sRes, count); //当count >= 100时,此处会导至程序crash.如何将代码改为
sRes.Format(IDS_USER_COUNT, count)或者sRes.Format(_T("Users: %d"), count),
可以正常运行.这里,
sRes.LoadString(IDS_USER_COUNT);
sRes.Format(sRes, count); //当count >= 100时,此处会导至程序crash.
这种写法肯定不好,但它在count>=100让我有些整不明白,各位能帮我解释一下吗,
先谢过了,我是知其然,不知其所以然,知道修改,但不知道为什么,呵呵.

解决方案 »

  1.   

    看看这个吧。也许有用。
    http://wflyfox.bokee.com/670276.html
      

  2.   

    关键是为什么count>=100才导致错误呢?
    随便说一下,这个程序用的是Unicode编码。
      

  3.   

    100会替换为把%d 3个字符,所以出错
    改为
    CString   sRes,sFormat; 
    sFormat.LoadString(IDS_USER_COUNT); 
    int count;
    count = 1000;
    sRes.Format(sFormat,    count);  
      

  4.   

    To hdt:
    再说详细一些嘛,我没有完全明白.
      

  5.   

    原因不在于被格式化的数据,也不在于LoadString有什么问题。而是CString::Format函数的问题。
    一般情况下,Format函数不允许将其本身格式化。比如:
            CString str="这样是不对的";
           str.Format("%s%d",str,100);
    这样就会导致错误。
    所以,如果要对一个字符串格式化,就应该写成这种格式:
            CString strFmt="这样就对了";
           CString str;
           str.Format("%s%d",strFmt,100);
      

  6.   

    严重同意一下7楼的意见!是的,不能只用一个变量,这中间需要一个变量来进行格式化的中转  CString   strFmt="这样就对了"; 
      CString   str; 
      str.Format("%s%d",strFmt,100); 这个代码看着就舒服多了!
      

  7.   

    是啊,他的代码不该那样写,可是,为什么在count<100的时候没有出问题呢?
      

  8.   

    CString::Format这个函数用自己来作参数是很危险的,根据语义,它会对"%d"这类的做替换。
     
    sRes.Format(sRes,   count);语义变为将内容为“Users:   %d”的字符串中的%d用对应整数的字符串替换,而此字符串本身又作为格式参数。会有%d替换的问题出现,当count>=100后,%d会被“100”替换,而此时替换的字符串是“100”,是三个字符组成,而此前的“%d”是两个字符组成,而这种用法本身迭代“%d“替换两次,所以当将"100"或类似超过两个字符组成的字符串拿来替换“%d”时,肯定会有越界访问发生。