静态代码分析是一个错误检测方法。 我们很高兴这种方法正变得越来越受欢迎的现在。 Visual Studio,包括静态分析作为它的许多特性有助于这个过程很大程度上。 这个特性很容易尝试和开始使用定期。 当我们理解一个喜欢静态代码分析,我们很高兴提供专业分析仪对语言的pv studio C / c++ / C + + 11。

介绍

Visual Studio开发环境允许您执行静态代码分析。 这个分析是非常有用的和易于使用的。 www.xiaoboedu.info然而,我们应该明白,Visual Studio执行大量的功能。 这意味着它的每个功能分开比不上专门的工具。 代码重构和着色功能不如在视觉协助。 集成的图像编辑的功能自然是比在Adobe Photoshop或平面设计。 这同样适用于静态代码分析功能。

但这都是理论化。 让我们搬到实践,看看有什么有趣的东西的pv工作室分析仪已经设法找到在Visual Studio 2012中文件夹。

我们实际上并没有计划要检查源文件包括到Visual Studio。 这是偶然发生的:许多头文件进行了一些修改,因为在Visual Studio 2012支持新语言标准C + + 11。 我们面临的任务以确保pvs工作室分析器可以处理这些头文件。

没想到我们注意到一些错误在头*。 h文件。 我们决定继续研究这些文件详细的Visual Studio 2012。 特别是,以下文件夹:

程序文件(x86)\ Microsoft Visual Studio 11.0 \ VC \包括
程序文件(x86)\ Microsoft Visual Studio 11.0 \ VC \ crt
程序文件(x86)\ Microsoft Visual Studio 11.0 \ \ atlmfc VC
 
  }
V501 有相同的子表达式的_Ctraits <泰>::_Isinf(真正的(左)) “左边和右边的“|”操作符|。 xcomplex 780

“ctr(泰)::_Isinf(真正的(左)) “表达式是重复了两次的条件。 我们不能肯定地说如果有一个误区,以何种方式的代码应该是固定的。 但这个函数显然是值得关注的。www.633816332.com

一个不必要的检查

template<typename BaseType, bool t_bMFCDLL = false>
class CSimpleStringT
{
  ....
  void Append(_In_reads_(nLength) PCXSTR pszSrc,
              _In_ int nLength)
  {
    ....
    UINT nOldLength = GetLength();
    if (nOldLength < 0)
    {
      // protects from underflow
      nOldLength = 0;
    }
  ....
};
V547 表达式的nOldLength < 0 '总是错误的。 无符号类型值是从不< 0。 atlsimpstr。 h 420

这里没有错误。 从代码中,字符串长度不能变得消极。 这个CSimpleStringT类包含相应的检查。 这个nOldLength变量具有无符号类型不会影响任何字符串长度是积极的,无论如何。 这仅仅是不必要的代码。

错误的字符串形成

template <class T>
class CHtmlEditCtrlBase
{
  ....
  HRESULT SetDefaultComposeSettings(
    LPCSTR szFontName=NULL, .....) const
  {
    CString strBuffer;
    ....
    strBuffer.Format(_T("%d,%d,%d,%d,%s,%s,%s"),
                     bBold ? 1 : 0,
                     bItalic ? 1 : 0,
                     bUnderline ? 1 : 0,
                     nFontSize,
                     szFontColor,
                     szBgColor,
                     szFontName);
    ....
  }
};
V576 不正确的格式。 考虑检查第八实际参数的“格式”功能。 字符串的指针的预计wchar_t类型符号。 afxhtml。 h 826

这段代码形式不正确的消息在UNICODE程序。 “格式() “功能预计第八参数有LPCTSTR类型,但“szFontName”变量总是会有LPCSTR类型。

港口与一个负数

typedef WORD ATL_URL_PORT;
class CUrl
{
  ATL_URL_PORT m_nPortNumber;
  ....
  inline BOOL Parse(_In_z_ LPCTSTR lpszUrl)
  {
    ....
    //get the port number
    m_nPortNumber = (ATL_URL_PORT) _ttoi(tmpBuf);
    if (m_nPortNumber < 0)
      goto error;
    ....
};
V547 表达式的m_nPortNumber < 0 '总是错误的。 无符号类型值是从不< 0。 atlutil。 h 2775

这个检查端口号码是零度以下不工作。 “m_nPortNumber”变量的无符号类型的词”。 “词”类型是“无符号短”。

未定义行为

Visual c++头文件包含以下宏。

#define DXVABitMask(__n) (~((~0) << __n))
无论它是使用,未定义行为发生。 当然,Visual c++开发人员更了解如果这种构造是否安全。 也许他们认为Visual c++总是会处理负数以同样的方式变化。 正式,一个负数转变导致未定义行为。 这个主题中详细讨论这篇文章” 韦德在未知的水域不。 第三部分 “。

不正确的操作在64位模式www.sijiaztan007.com

这种模式的64位错误中详细讨论一系列教训我们已经写在64位的C / c++软件开发。 理解这一点的错误,请见 第十二课 。

class CWnd : public CCmdTarget
{
  ....
  virtual void WinHelp(DWORD_PTR dwData,
                       UINT nCmd = HELP_CONTEXT);
  ....
};

class CFrameWnd : public CWnd
{
  ....
};

class CFrameWndEx : public CFrameWnd
{
  ....
  virtual void WinHelp(DWORD dwData,
                       UINT nCmd = HELP_CONTEXT);
  ....
};
V301 意想不到的函数重载的行为。 看到第一个参数的函数的WinHelpW在派生类的CFrameWndEx”和基类的CFrameWnd”。 afxframewndex。 h 154 www.yangyueedu.info   

 
  {
    CMFCToolBarButton* pButtonCurr =
      (CMFCToolBarButton*)lstOrigButtons.GetNext(posCurr);

    UINT uiID = pButtonCurr->m_nID;

    if ((pButtonCurr == NULL) ||
        (pButtonCurr->m_nStyle & TBBS_SEPARATOR) ||
        (....)
    {
      continue;
    }
  ....
}
 
  NULL);
同样的错误可以在这里找到:

V547表达式“(0)>(m_uiPopupTimerDelay - 1) “永远是错误的。 无符号类型值是从不< 0。 afxribbonpanelmenu。 cpp 880
一个毫无意义的字符串

BOOL CMFCTasksPaneTask::SetACCData(CWnd* pParent, CAccessibilityData& data)
{
  ....
  data.m_nAccHit = 1;
  data.m_strAccDefAction = _T("Press");
  data.m_rectAccLocation = m_rect;
  pParent->ClientToScreen(&data.m_rectAccLocation);
  data.m_ptAccHit;
  return TRUE;
}
V607 无主的表达”data.m_ptAccHit”。 afxtaskspane。 cpp 96

什么是“数据。 m_ptAccHit;”? 也许程序员想分配一些值的变量但忘了吗?

额外的0可能丢失

BOOL CMFCTasksPane::GetMRUFileName(....)
{
  ....
  const int MAX_NAME_LEN = 512;

  TCHAR lpcszBuffer [MAX_NAME_LEN + 1];
  memset(lpcszBuffer, 0, MAX_NAME_LEN * sizeof(TCHAR));

  if (GetFileTitle((*pRecentFileList)[nIndex],
                   lpcszBuffer, MAX_NAME_LEN) == 0)
  {
    strName = lpcszBuffer;
    return TRUE;
  }
  ....
}
V512 一个叫“memset”功能将导致底流的缓冲的lpcszBuffer”。 afxtaskspane。 cpp 2626

我怀疑这段代码可能会返回一个字符串,不会结束与一个终端null。 最有可能的是,过去的数组项应该被清理过:

memset(lpcszBuffer, 0, (MAX_NAME_LEN + 1) * sizeof(TCHAR));
奇怪的“如果”

void CMFCVisualManagerOfficeXP::OnDrawBarGripper(....) www.huayuepx.info 
{
  ....
    if (bHorz)
    {
      rectFill.DeflateRect(4, 0);
    }
    else
    {
      rectFill.DeflateRect(4, 0);
    }
  ....
}