微软托管环境已经出来好多年了,作为非托管环境下运行的VC,虽然它的编程效率比托管编程低多了,但是它能生存到今天,也足见它的强大!

但是VC使用比起.net Framework来确实比较难,常常令有经验的软件工程师也耗费大量的时间。最近由于一个小小的环境设置设置问题花了很多时间,这跟用惯了VC6突然转到VC2005有关,写出来让大家参考参考!

一。字符集设置不同系统调用的函数也不同

我不知道VC.net2005默认工程默认设置是采用“Unicode字符集”(Unicode Character Set)的,以前用VC6工程的时候默认是“多字符集”(Multi-Byte Character Set)的。

我声明了一个CString,按计划给它赋值,就像下面:

CString s;

s.Format(“count = %d”,count);

如果是采用Multi-Byte Character Set是不会有错误的,因为这是我的环境采用的Unicode字符集的,而我给CString的Format函数是“多字符集”(Multi-Byte)所以编译不通过,要知道在这种设置下使用MessageBox(“ddd”);编译是不会通过的,因为系统调用的是MessageBoxW,即Unicode宽字符集的那个函数。

根据编译器的提示把s.Format(“count = %d”,count);改成s.Format(_T(“count = %d”,count);就搞定了,_T代表一个宏,宏的意思就是把字符串转成宽字符表示。同样的,MessageBox(“ddd”);可以为MessageBox(_T(“ddd”));

但是还有个问题就是,所有窗体显示的东西都是宽字符的,例如a在内存里就是a/0两个字节,前面一个字节a后面是/0,当从窗体取下数据(例如用户输入)要跟其他平台交互时,例如网络传输到远端机器。如果那边使用的不是Unicode字符集,就会出问题,为了使界面和后台传输一致,只好使用把宽字符转换成多字符集表示:

CString strWideChar;

strWideChar.Format(_T(“这是宽字节哦”));

char buf[20];

memset(buf,0,20);

WideCharToMultiByte(  //转换Unicode到Ansi

CP_ACP,

WC_COMPOSITECHECK | WC_DEFAULTCHAR,

strWideChar,

strWideChar.GetLength(),

(char *)buf,  //转换到缓冲区中

20,  //最多个字节

0,

0

);

同样的,你接收到的字符串想要在界面正常显示,还必须把它转换成宽字节表示:

char chBytes[8];

memcpy(chBytes,”aaaaaaa/ 0”,8);

WCHAR wch[9];

n = MultiByteToWideChar( //转换Unicode到Ansi

CP_ACP,

0,

chBytes,

8,

wch,  //转换到缓冲区中

8  //最多个字节

);

wch[n] = '/0';

这样每次从界面取数据和把数据显示到界面上都要先做处理,但是也可以把编译环境设置成“多字符集”(Multi-Byte Character Set),就可以避免这样转换来转换去。就是在”Project->Configuration Properties->General->Character Set,选择“Use Unicode Character Set”就是使用Uncode字符集,选择” Use Multi-Byte Character Set”就是多字节字符集。

二。字符集设置造成函数调用的失败

我在CodeProject上找了一个很厚道的老外写的一个继承了CDialog窗体类CResizableDialog的源码,这个类的作用是使MFC的窗体放大缩小时,窗体上的控件可以定位(Auchor),不要小看这个小小的每天都要用到的功能,用MFC实现真的很麻烦。很佩服那个老外写了那么多代码。

我拿了那个现成的工程,直接在我的工程里引用他的工程。Everything works perfect。直到我把项目发布成Release的,双击运行后没有任何反应,Very weird!后来我用MessageBox打印消息,发现运行到DoModal函数里面就没有出来,程序直接退出了!使用try,catch都得不到错误!因为我的窗体是继承老外写的窗体类来的,原先继承CDialog是好好的,问题肯定在他的工程里面,可是他给的示例程序没有任何问题啊。

我又拿一个前的测试程序,让它从CResizableDialog继承,也没有任何问题。

一时间不知道哪里出现了问题,Release又不能像Debug那样调试,打了一堆MessageBox后还是不知道问题出现在哪里。凭着经验,可以知道程序中可能出现了内存的越界访问什么的致命错误,才会导致程序“一声不吭”地退出,但是究竟哪里出了问题呢?

就在束手无策的时候,我发现调用CResizableDialog的成员函数EnableSaveRestore会引发链接错误:“未定义的外部符号”,不引用它不会出错,测试程序引用它没有任何错误。通常这个错误造成是因为引用函数在.h文件里声明了,但是在.cpp里面没有定义,或者.cpp文件里的定义和.h上的函数签名不一样。但是此时不可能是这个错误,因为测试程序没有错误啊。直觉告诉我这是解决“Release后程序直接退出的关键”,说不定这个函数调用的问题解决了Release的问题也解决了。

既然调用EnableSaveRestore出现了不该出现的错误,那么就从这个函数开始找。这个函数是这样的:

.h文件声明

void EnableSaveRestore(LPCTSTR pszSection, BOOL bRectOnly = FALSE);

.cpp文件定义

void CResizableDialog::EnableSaveRestore(LPCTSTR pszSection, BOOL bRectOnly/* = FALSE */)

{

m_sSection = pszSection;

m_bEnableSaveRestore = TRUE;

m_bRectOnly = bRectOnly;

// restore immediately

LoadWindowRect(pszSection, bRectOnly);

}

上面的代码没有任何错误,既然没有错误,就要用使用以下方法来找:

1.重新为CResizableDialog写一个函数,它没有参数的,调用它,发现没有错误,看来参数有问题。

2.既然没有参数的函数没有错误,就把出问题的函数参数去掉吧,竟然也没有错误!那问题就肯定是出在参数上。

3.去掉其中一个参数,测试发现是LPCTSTR pszSection的问题,而不是BOOL bRectOnly的问题。

4.既然这样,那就换一种表示吧,把LPCTSTR pszSection换成WCHAR* pszSection,运行它,竟然不出错了!翻开MFC宏定义,就会发现其实LPCTSTR和WCHAR*是一样的!

5.但是这个函数功能还是不正常,断点进入那个函数里面发现传进去的字符串只有一个字符了,这种情况就是宽字符当成短字符时,第二个字节的/0当成了字符串的截止字符了,也就是说,这个函数里采用的是短字符(多字符集Multi Byte)处理的。

6.我的工程采用的是宽字符集(Unicode Char)的,检查设置,原来那个老外是用VC6编的,默认是使用多字符集(Multi Byte)的,VC真是笨啊,两个Project在一个Solution里面完全不同的设置竟然没有任何提示,简直把我弄死了!

7.把引用工程也改成使用Unicode字符集,并且把函数EnableSaveRestore WCHAR* pszSection恢复原样,搞定!果然不出我所料,Release也没有问题了!

看来VC排错需要 一点技巧啊。

VC2005字符集设置容易出错的问题!相关推荐

  1. linux mysql设置数据库utf_Linux系统下MySQL数据库服务器字符集设置

    Linux认证考试:Linux系统下的MySQL数据库服务器字符集设置 启动MySQL后,以root登录mysql isher@isher-ubuntu:~$ mysql -u root >sh ...

  2. 再见乱码:5分钟读懂MySQL字符集设置

    一.内容概述 在MySQL的使用过程中,了解字符集.字符序的概念,以及不同设置对数据存储.比较的影响非常重要.不少同学在日常工作中遇到的"乱码"问题,很有可能就是因为对字符集与字符 ...

  3. linux mysql 客户端编码设置_mac和linux下mysql字符集设置问题

    为什么要设置字符集 设置字符集主要是解决乱码问题,由于中文和英文编码不同导致,中文出现乱码,所以一般都设置为utf8格式 不同的字符集占用的字节大小不同,选择合适的字符集可以提高数据库的性能, mac ...

  4. mysql的字符集设置为什么_为什么Mysql默认的字符集都是latin1

    为什么Mysql默认的字符集都是latin1 关注:151  答案:2  mip版 解决时间 2021-01-25 17:36 提问者旧梦已过期 2021-01-25 03:58 为什么Mysql默认 ...

  5. Ubuntu下mysql字符集设置

    Liunx下修改MySQL字符集: 1.查找MySQL的cnf文件的位置 find / -iname '*.cnf' -print /usr/share/mysql/my-innodb-heavy-4 ...

  6. MySQL数据库端字符集设置

    最近,在项目组使用的mysql数据库中,插入数据出现乱码,关于这个问题做了下总结,我们从最基本的地方说起,到错误产生的深层次原因和解决办法. 基本概念 • 字符(Character)是指人类语言中最小 ...

  7. Eclipse更改默认字符集 设置UTF-8

    http://rebecca.iteye.com/blog/654953 Eclipse更改默认字符集 设置UTF-8 eclipse 中UTF-8设置 1.windows->Preferenc ...

  8. c mysql 设置字符集_MYSQL字符集设置的方法详解(终端的字符集)

    前言 每次利用终端 创建数据库或者创建表的时候,字符集都是latin1,或者进行插入值的时候,显示的是乱码(不指定字符集的时候)如下: 查看当前数据库的字符集 character_set_client ...

  9. mysql 存取字符集_MySQL字符集设置—MySQL数据库乱码问题详解

    MySQL(4.1以后版本) 服务器中有六个关键位置使用了字符集的概念,他们是:client .connection.database.results.server .system.MySQL有两个字 ...

  10. mysql数据库字符集设置_查看和设置MySQL数据库字符集

    查看和设置MySQL数据库字符集作者:scorpio 2008-01-21 10:05:17 标签: 杂谈 Liunx下修改MySQL字符集:1.查找MySQL的cnf文件的位置find / -ina ...

最新文章

  1. Java长见到的面试题,看你能答出几题,就知道自己有多菜了
  2. 腾讯汤道生:人工智能最大的价值是“服务于人”
  3. 自制ACL+DHCP实验(初版)
  4. 全国大学生智能车单车行进组中的单车改造飞轮安装方案参考
  5. 全国大学生智能汽车竞赛获奖证书文字
  6. Codeforces 963A Alternating Sum 【数论+数学】
  7. 一道简单的python面试题-购物车
  8. 2019年第十届蓝桥杯 - 省赛 - C/C++大学B组 - D. 数的分解
  9. unity让对象作为参数_unity-container – 一个unity容器可以将自身的引用作为构造函数参数传递吗?...
  10. linux两台服务器 同一个地址_【网工玩Linux】搭建开源多运营商(ISP)链路负载均衡器...
  11. 量化交易(图文版其二)
  12. [JavaScript] 判断网页能不能被IFrame 嵌入
  13. db2存储过程手动执行没有问题_轻松解决DB2创建存储过程时遇到的错误
  14. KEmulator与eclipse的集成
  15. selenium firebug firePath xpath问题
  16. 海量数据和高并发下的 Redis 业务优化实践
  17. 计算机打印怎么取消,打印机如何取消打印作业?如何删除打印作业?
  18. 中国联通5G网络架构
  19. WIndows禁用笔记本键盘
  20. 大学生转入计算机专业申请书,计算机系大学生助学金申请书1000字

热门文章

  1. 脉冲耦合神经网络(PCNN)-pulse coupled neural network
  2. ffmpeg完全教程
  3. 2019奥斯卡谁是赢家 这里有一份来自AI的预测名单
  4. 『神器』如何免费下载百度文库付费资料?
  5. RMAN数据库完全备份和恢复
  6. 斐讯K2路由器,版本号V22.6.507.43(最新)刷华硕固件简明教程(附所有工具包)
  7. 数字图像处理MFC程序设计之图像的打开显示
  8. php 跨域解决方案
  9. Udacity数据分析(入门)-TMDb电影数据集探索
  10. 程序员看过都说好的资源网站,你懂得!