提高程序质量的注意事项
Author: brike.huang
Email: brike.huang_at_163.com
QQ: 24558102
Date: 2008.05
——————–
以下是我从事windows开发的一些心得,希望对各位有所帮助。
软件开发,比较重要是软件需求、进度控制、质量管理等,本主题主要讨论质量——程序的质量程序的质量,主要表现在以下几方面:
1稳定性
2可移植性
3兼容性
4可维护性
…….
=================
1.使用中性的数据类型,避免使用绝对数据类型(除非有需求)
在程序中尽量使用INT,TCHAR,LPTCSTR,DWORD等类型,如果是指针,可以使用VOID,PVOID或DWORD_PTR、 ULONG_PTR、UINT_PTR类型在UNICODE环境下,TCHAR定义为unsigned short,在ASCII环境下定义为char类型……
在64位环境下,PVOID、XXXX_PTR等类型长度为8Bytes,在32位环境下,为4Bytes。xxxx_PTR数据类型需要SDK支持,该类型对64位服务器版本的程序影响比较大,程序有可能会使用到大于4G的地址空间
2.使用中性的函数
很多函数有多种形态,最常见的是UNICODE与ASCII,64位与32位。
如:_tcslen,UNICODE环境下定义为wcslen(用于处理UNICODE字符串长度),ASCII环境下定义为strlen(用于处理ASCII字符串长度)
使用GetWindowLongPtr代替GetWindowLong,有很多类似的API,具体请参考SDK
3.使用UNICODE编译环境
windows2000及以后的系统,已经是纯UNICODE环境了。ASCII环境下处理亚洲文字时,容易出现乱码。
具体方法:在编译条件中加入_UNICODE、UNICODE符号定义,在链接时指定程序入口
windows程序入口:wWinMainCRTStartup
console程序入口:wMainCRTStartup
dll程序入口:wDllMainCRTStartup
在程序中,有可能必须使用ASCII(比如与COM通讯),程序中应该增加相应处理:
#ifdef UNICODE
…
#else
…
#endif
4.使用安全的字符处理方法
使用strsafe.h中的函数,而不是默认的
如StringCbCopy代替_tcscpy(ASCII对应strcpy),StringCbCat代替代_tcscat(ASCII对应strcat)。能有效的防止内存溢出
5.初始化变量
比如,定义了TCHAR szBuffer[254],然后通过一个API取得一个字串。但该API调用失败,此时反应到UI上是一串乱七八糟的东西,更严重的后果是导致程序运行崩溃。
一般把变量全部初始化0,如:TCHAR szBuffer[254] = {0};
6.条件运算时,常数或不能改变的变量作为第一目运算符
如经常犯的错误: if (n == 3) …错写成
if (3 = n) ….
编译时直接给出错误信息
如果写成
if (n = 3),在成千上万的代码中,要找到它,会让人发狂
7.注意API版本的说明
有部分API在新版本的OS中才支持,如果程序要在旧版本的OS运行,因在DLL中找不到链接符号,而终止运行
比如:SetupDiCreateDeviceInfoListEx,SDK中的相关描述如下:
Client: Requires Windows XP or Windows 2000 Professional.
Server: Requires Windows Server 2003 or Windows 2000 Server.
如果程序是隐性链接并对应的Setupapi.dll没附带进安装路径,程序在windows2000以下版本上将不能运行
8.在程序中使用调试用语
如_RPTF0、_RPTF1、…..可以在VC的Output窗口或DbgView之类型的工具查看程序运行状态,在容易出生错误的地方使用assert之类的用语,在程序崩溃时会告诉开发人员哪行代码出现问题
9.分配的内存一定要初始化,并说明在什么条件下使用什么函数释放(free?delete?HeapFree?…..)
一般情况下初始化为0,理由与第5条“初始化变量”相同。
如果是小型程序,并申请的内存不多,很多人偷懒不做这个烦人的动作。我有一擅长VB与.net的同事,做图形处理,程序处理不到几张图片,就消耗掉所有内存,最先想到的办法就是买内存条,结果只是增加了几张图片的吞吐量,后来采取关程序,再开程序的方法运行。一个小组七八人花了一个多月都找不到问题。最后在我拜访他们部门时,花了不到半小时就解决了。
10.提升编译警告级别
如果使用VC6,默认为/W3,SDK默认为/W4。SDK在编译时就能发现更多隐性问题。
———————
以上几个规则都是很容易做到的,我个人比较喜欢使用UNICODE、64BIT的AMD编译链接SDK环境,在这个环境下写程序,一般不会遇到兼容或移植上的问题,代码不用做多大的变化,就可以应用到WINDOWS各个版本上,只需要在不同的编译条件下重新Rebuild。
以下提供一个SAMPLE:
C++代码
1. #include
2. #include
3. #include
4. #include
5. #define OPTIONAL_LEN 10
6.
7. #ifdef _DEBUG
8. #define DEBUG_PRINT1(IF, msg, arg1) if (!(IF)) _RPTF1(_CRT_WARN, msg, arg1)
9. #else
10. #define DEBUG_PRINT1 // Release版本该语句为空
11. #endif
12.
13. INT _tmain(INT argc, TCHAR* argv[])
14. {
15. TCHAR szOptional[3][OPTIONAL_LEN] = {0};
16.
17. DEBUG_PRINT1(3 <= argc, ("arg number: %d\n"), argc); // 如果参数数量小于3,则输出调试信息 [5/12/2008]
18.
19. if (3 > argc) return -1;
20.
21. for (INT n = 0; 3 > n; ++n)
22. {
23. StringCbCopy(szOptional[n], sizeof(TCHAR) * OPTIONAL_LEN, __argv[n]); // 保存参数的长度不超过
24.
25. OPTIONAL_LEN个字符 [5/12/2008]
26. _tprintf(_T(“arg%d: %s\n”), n, szOptional[n]);
27. }
28. return 0;
29. }
—————
以上程序兼容UNICODE、防止内存溢出
标签: win32
