设为首页 加入收藏

TOP

C++编程丨让你的C++代码变的更加健壮!(一)
2019-03-25 18:07:57 】 浏览:236
Tags:编程 代码 更加 健壮

介绍

在实际的项目中,当项目的代码量不断增加的时候,你会发现越来越难管理和跟踪其各个组件,如其不善,很容易就引入BUG。因此,我们应该掌握一些能让我们程序更加健壮的方法。

这篇文章提出了一些建议,能有引导我们写出更加健壮的代码,以避免产生灾难性的错误。即使、因为其复杂性和项目团队结构,你的程序目前不遵循任何编码规则,按照下面列出的简单的规则可以帮助您避免大多数的崩溃情况。

背景

先来介绍下作者开发一些软件(CrashRpt),你可以http://code.google.com/p/crashrpt/网站上下载源代码。CrashRpt 顾名思义软件崩溃记录软件(库),它能够自动提交你电脑上安装的软件错误记录。它通过以太网直接将这些错误记录发送给你,这样方便你跟踪软件问题,并及时修改,使得用户感觉到每次发布的软件都有很大的提高,这样他们自然很高兴。

在分析接收的错误记录的时候,我们发现采用下文介绍的方法能够避免大部分程序崩溃的错误。例如:局部变量未初始化导致数组访问越界,指针使用前未进行检测(NULL)导致访问访问非法区域等。

我已经总结了几条代码设计的方法和规则,在下文一一列出,希望能够帮助你避免犯一些错误,使得你的程序更加健壮。

Initializing Local Variables (局部变量初始化)

使用未初始化的局部变量是引起程序崩溃的一个比较普遍的原因,例如、来看下面这段程序片段:

// Define local variables

BOOL bExitResult; // This will be TRUE if the function exits successfully

FILE* f; // Handle to file

TCHAR szBuffer[_MAX_PATH];   // String buffer

 

// Do something with variables above...

上面的这段代码存在着一个潜在的错误,因为没有一个局部变量初始化了。当你的代码运行的时候,这些变量将被默认负一些错误的数值。例如bExitResult 数值将被负为-135913245 ,szBuffer?必须以“”结尾,结果不会。因此、局部变量初始化时非常重要的,如下正确代码:

// Define local variables

// Initialize function exit code with FALSE to indicate failure assumption

BOOL bExitResult = FALSE;

// This will be TRUE if the function exits successfully

// Initialize file handle with NULL

FILE* f = NULL; // Handle to file

// Initialize string buffer with empty string

TCHAR szBuffer[_MAX_PATH] = _T("");   // String buffer

// Do something with variables above...

注意:有人说变量初始化会引起程序效率降低,是的,确实如此,如果你确实非常在乎程序的执行效率,去除局部变量初始化,你得想好其后果。

Initializing WinAPI Structures

许多Windows API都接受或则返回一些结构体参数,结构体如果没有正确的初始化,也很有可能引起程序崩溃。大家可能会想起用ZeroMemory宏或者memset()函数去用0填充这个结构体(对结构体对应的元素设置默认值)。但是大部分Windows API 结构体都必须有一个cbSIze参数,这个参数必须设置为这个结构体的大小。

看看下面代码,如何初始化Windows API结构体参数:

NOTIFYICONDATA nf; // WinAPI structure

memset(&nf,0,sizeof(NOTIFYICONDATA)); // Zero memory

nf.cbSize = sizeof(NOTIFYICONDATA); // Set structure size!

// Initialize other structure members

nf.hWnd = hWndParent;

nf.uID = 0;  

nf.uFlags = NIF_ICON | NIF_TIP;

nf.hIcon = ::LoadIcon(NULL, IDI_APPLICATION);

_tcscpy_s(nf.szTip, 128, _T("Popup Tip Text"));

// Add a tray icon

Shell_NotifyIcon(NIM_ADD, &nf);

注意:千万不要用ZeroMemory和memset去初始化那些包括结构体对象的结构体,这样很容易破坏其内部结构体,从而导致程序崩溃.

// Declare a C++ structure

struct ItemInfo

{

  // The structure has std::string object inside

  std::string sItemName;

  int nItemValue;

};

 

// Init the structure

ItemInfo item;

// Do not use memset()! It can corrupt the structure

// memset(&item, 0, sizeof(ItemInfo));

// Instead use the following

item.sItemName = "item1";

item.nItemValue = 0;

这里最好是用结构体的构造函数对其成员进行初始化.

// Declare a C++ structure

struct ItemInfo

{

    // Use structure constructor to set members with default values

    ItemInfo()

    {

      sItemName = _T("unknown");

      nItemValue = -1;

    }

 

    std::string sItemName; // The structure has std::string object inside

    int nItemValue;

};

// Init the structure

ItemInfo item;

// Do not use memset()! It can corrupt the structure

// memset(&item, 0, sizeof(ItemInfo));

// Instead use the following

item.sItemName = "item1";

item.nItemValue = 0;

Validating Function Input

在函数设计的时候,对传入的

首页 上一页 1 2 3 4 5 下一页 尾页 1/5/5
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇#leetcode刷题之路33-搜索旋转排.. 下一篇5分钟速成C++14多线程编程

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目