博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Making your C++ code robust<three>
阅读量:6815 次
发布时间:2019-06-26

本文共 6275 字,大约阅读时间需要 20 分钟。

hot3.png

  • Cleaning Up Released Handles 

      在释放一个句柄之前,务必将这个句柄复制伪NULL (0或则其他默认值)。这样能够保证程序其他地方不会重复使用无效句柄。看看如下代码,如何清除一个Windows API的文件句柄:

HANDLE hFile = INVALID_HANDLE_VALUE;     // Open file  hFile = CreateFile(_T("example.dat"), FILE_READ|FILE_WRITE, FILE_OPEN_EXISTING);  if(hFile==INVALID_HANDLE_VALUE)  {    return FALSE; // Error opening file  }   // Do something with file   // Finally, close the handle  if(hFile!=INVALID_HANDLE_VALUE)  {    CloseHandle(hFile);   // Close handle to file    hFile = INVALID_HANDLE_VALUE;   // Clean up handle  }

下面代码展示如何清除File *句柄:

// First init file handle pointer with NULL  FILE* f = NULL;   // Open handle to file  errno_t err = _tfopen_s(_T("example.dat"), _T("rb"));  if(err!=0 || f==NULL)    return FALSE; // Error opening file   // Do something with file   // When finished, close the handle  if(f!=NULL) // Check that handle is valid  {    fclose(f);    f = NULL; // Clean up pointer to handle  }

  • Using delete [] Operator for Arrays 

     如果你分配一个单独的对象,可以直接使用new ,同样你释放单个对象的时候,可以直接使用delete . 然而,申请一个对象数组对象的时候可以使用new,但是释放的时候就不能使用delete ,而必须使用delete[]:

// Create an array of objects CVehicle* paVehicles = new CVehicle[10]; delete [] paVehicles; // Free pointer to array paVehicles = NULL; // Set pointer with NULLor // Create a buffer of bytes LPBYTE pBuffer = new BYTE[255]; delete [] pBuffer; // Free pointer to array pBuffer = NULL; // Set pointer with NULL

  • Allocating Memory Carefully 

     有时候,程序需要动态分配一段缓冲区,这个缓冲区是在程序运行的时候决定的。例如、你需要读取一个文件的内容,那么你就需要申请该文件大小的缓冲区来保存该文件的内容。在申请这段内存之前,请注意,malloc() or new是不能申请0字节的内存,如不然,将导致malloc() or new函数调用失败。传递错误的参数给malloc() 函数将导致C运行时错误。如下代码展示如何动态申请内存:

// Determine what buffer to allocate.  UINT uBufferSize = GetBufferSize();    LPBYTE* pBuffer = NULL; // Init pointer to buffer   // Allocate a buffer only if buffer size > 0  if(uBufferSize>0)   pBuffer = new BYTE[uBufferSize];

 为了进一步了解如何正确的分配内存,你可以读下这篇文章。

  • Using Asserts Carefully

       Asserts用语调试模式检测先决条件和后置条件。但当我们编译器处于release模式的时候,Asserts在预编阶段被移除。因此,用Asserts是不能够检测我们的程序状态,错误代码如下:

#include 
// This function reads a sports car's model from a file CVehicle* ReadVehicleModelFromFile(LPCTSTR szFileName) { CVehicle* pVehicle = NULL; // Pointer to vehicle object // Check preconditions assert(szFileName!=NULL); // This will be removed by preprocessor in Release mode! assert(_tcslen(szFileName)!=0); // This will be removed in Release mode! // Open the file FILE* f = _tfopen(szFileName, _T("rt")); // Create new CVehicle object pVehicle = new CVehicle(); // Read vehicle model from file // Check postcondition assert(pVehicle->GetWheelCount()==4); // This will be removed in Release mode! // Return pointer to the vehicle object return pVehicle; }

  看看上述的代码,Asserts能够在debug模式下检测我们的程序,在release 模式下却不能。所以我们还是不得不用if()来这步检测操作。正确的代码如下;

CVehicle* ReadVehicleModelFromFile(LPCTSTR szFileName, )  {    CVehicle* pVehicle = NULL; // Pointer to vehicle object     // Check preconditions    assert(szFileName!=NULL); // This will be removed by preprocessor in Release mode!    assert(_tcslen(szFileName)!=0); // This will be removed in Release mode!     if(szFileName==NULL || _tcslen(szFileName)==0)      return NULL; // Invalid input parameter     // Open the file    FILE* f = _tfopen(szFileName, _T("rt"));     // Create new CVehicle object    pVehicle = new CVehicle();     // Read vehicle model from file     // Check postcondition     assert(pVehicle->GetWheelCount()==4); // This will be removed in Release mode!     if(pVehicle->GetWheelCount()!=4)    {       // Oops... an invalid wheel count was encountered!        delete pVehicle;       pVehicle = NULL;    }     // Return pointer to the vehicle object    return pVehicle;  }

  • Checking Return Code of a Function 

        断定一个函数执行一定成功是一种常见的错误。当你调用一个函数的时候,建议检查下返回代码和返回参数的值。如下代码持续调用Windows API ,程序是否继续执行下去依赖于该函数的返回结果和返回参数值。

HRESULT hres = E_FAIL;    IWbemServices *pSvc = NULL;    IWbemLocator *pLoc = NULL;        hres =  CoInitializeSecurity(        NULL,         -1,                          // COM authentication        NULL,                        // Authentication services        NULL,                        // Reserved        RPC_C_AUTHN_LEVEL_DEFAULT,   // Default authentication         RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation          NULL,                        // Authentication info        EOAC_NONE,                   // Additional capabilities         NULL                         // Reserved        );                          if (FAILED(hres))    {        // Failed to initialize security        if(hres!=RPC_E_TOO_LATE)            return FALSE;    }        hres = CoCreateInstance(        CLSID_WbemLocator,                     0,         CLSCTX_INPROC_SERVER,         IID_IWbemLocator, (LPVOID *) &pLoc);    if (FAILED(hres) || !pLoc)    {        // Failed to create IWbemLocator object.         return FALSE;                   }       hres = pLoc->ConnectServer(         _bstr_t(L"ROOT\\CIMV2"), // Object path of WMI namespace         NULL,                    // User name. NULL = current user         NULL,                    // User password. NULL = current         0,                       // Locale. NULL indicates current         NULL,                    // Security flags.         0,                       // Authority (e.g. Kerberos)         0,                       // Context object          &pSvc                    // pointer to IWbemServices proxy         );        if (FAILED(hres) || !pSvc)    {        // Couldn't conect server        if(pLoc) pLoc->Release();             return FALSE;      }    hres = CoSetProxyBlanket(       pSvc,                        // Indicates the proxy to set       RPC_C_AUTHN_WINNT,           // RPC_C_AUTHN_xxx       RPC_C_AUTHZ_NONE,            // RPC_C_AUTHZ_xxx       NULL,                        // Server principal name        RPC_C_AUTHN_LEVEL_CALL,      // RPC_C_AUTHN_LEVEL_xxx        RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx       NULL,                        // client identity       EOAC_NONE                    // proxy capabilities     );    if (FAILED(hres))    {        // Could not set proxy blanket.        if(pSvc) pSvc->Release();        if(pLoc) pLoc->Release();             return FALSE;                   }

转载于:https://my.oschina.net/kaixindewo/blog/34437

你可能感兴趣的文章
SOA面向服务化编程架构(dubbo)
查看>>
sphinx全文索引开源
查看>>
junit测试套件
查看>>
向一个网站发请求的几种方式
查看>>
UVA - 10245 The Closest Pair Problem
查看>>
利用Bootstrap制作一个流行的网页
查看>>
大型网站架构 图片服务器分离
查看>>
【设计模式】迭代器模式(Iterator )
查看>>
Linux ssh安全设置
查看>>
LVM逻辑卷管理
查看>>
ubuntu:重装之后软件安装流程
查看>>
python读写不同编码txt文件
查看>>
Linux 基本命令(持续更新ing)
查看>>
java基础必备单词讲解 day six
查看>>
第7章 SpringMVC高级技术
查看>>
C语言结构体里的成员数组和指针
查看>>
【转】AlphaGo Zero 和强人工智能
查看>>
二维凸包
查看>>
怎么用SQL查询昨天、今天、明天和本周的记录?又怎么用SQL查询一天,三天,一周,一个月,更长一些——一个季度的记录呢...
查看>>
c 冒泡排序
查看>>