技术文章翻译(四) -- 现代C++避免产生BUG的相关技术

本人声明

1.本栏仅为归档自己看到的优秀文章;
2.文章版权归原作者所有;
3.因为个人水平有限,翻译难免有错误,请多多包涵。

原文地址

https://www.codeguru.com/cpp/cpp/how-to-avoid-bugs-using-modern-c-160915050508.html

文章正文

现代C++避免产生BUG的相关技术

作者: el_programmer 发表于:2017.04.14

  • 摘要
    C ++的一个主要问题就是是拥有大量的行为未定义的对象,或者出乎程序员意料的异常。当我们在对各种项目进行静态分析时,我们经常会遇到它们。但是,最好的办法是在编译阶段检测到错误,这一点是总所周知的。在现代C++,有些技术不仅可以使我们编写更加简单清晰的代码,还可以使代码更加安全可靠。下面就让我们看看这样的技术有哪些。

  • 什么是现代C++语言?
    在C ++11发布之后,现代C ++这个术语变得非常流行。这是术语是什么意思呢?首先,现代C++是一组编程模式和编程风格的集合,它的目的是消除”旧C++“的缺点;而”旧C++“是很多C++程序员所习惯的C++,特别是那些从C语言开始编程的程序员。C ++11看起来更加简洁易懂,这一点是非常重要的。
    人们在谈论现代C++时通常会想到什么?并行性,编译时运算,资源获取就是初始化,lambdas表达式,范围,概念,模块和标准库中其他同等重要的组件(例如,用于处理文件系统的API)。这些都是非常酷的现代化的概念,我们期待在下一组标准中看到它们。但是,我想请大家注意的是如何利用新标准写出更安全的代码。在运用静态分析工具时,我们看到了许多不同的错误,有时我们不禁会想:“在现代C ++中,这些错误本来是可以避免的”。因此,我建议我们来检查几个错误,这些错误是我们运用PVS-Studio软件在各种开源项目中发现的。此外,我们也将看到如何修复这些错误。

  • 自动类型推断
    在C ++11中,添加了关键字auto和decltype。当然,你已经知道它们是如何工作的。

std::map<int, int> m; 
auto it = m.find(42); 
//C++98: std::map&amp;lt;int, int&amp;gt;::iterator it = m.find(42);

在不损失代码可读性的情况下,缩短长类型非常方便。但是,这些关键字与模板一起变得非常广泛:不需要使用auto和decltype指定返回值的类型。

但是让我们回到我们之前的话题。这里有一个64位程序错误的例子。

string str = .....; 
unsigned n = str.find("ABC"); 
if (n != string::npos)

在64位应用程序中,string :: npos的值大于UINT_MAX的最大值,UINT_MAX可以由无符号类型的变量表示。在这种情况下,我们就可以利用auto将我们从这类问题中解救出来。这是因为n变量的类型对我们来说并不重要,它主要的是用来容纳string :: find的所有可能值。事实上,如果我们用auto重写这个例子,那么错误就不存在了:

string str = .....; 
auto n = str.find("ABC"); 
if (n != string::npos)

但并非所有的事情都是这么简单的。使用auto也不是解决问题的灵丹妙药,与其使用过程中,也存在很多相关的陷阱。例如,您可以编写如下代码:

auto n = 1024 * 1024 * 1024 * 5; 
char* buf = new char[n];

Auto并不会将我们从整数移出的问题中解救出来,而且为缓冲区分配的内存将少于5G。

当涉及到一个非常常见的错误(编程错误的循环)时,Auto也无法提供任何帮助。让我们来看一个例子:

std::vector<int> bigVector; 
for (unsigned i = 0; i<bigVector.size(); ++i) 
{ ... }

注意:
原文中的代码为:
std::vectorlt;intgt; bigVector;
for (unsigned i = 0; i lt; bigVector.size(); ++i)
{ … }
个人认为是输入错误,结合下面的代码做了调整。

对于数据规模很大的数据,此循环变为无限循环。代码中存在这样的错误并不奇怪:这是因为它们在比较罕见的情况下才能暴露出来,或者没有测试到。

我们可以用auto重写这段代码吗?

std::vector<int> bigVector; 
for (auto i = 0; i < bigVector.size(); ++i) 
{ ... }

结果是不行的。不仅错误依然存在,而且它带来了更严重的问题。

简单自动类型推断的表现非常糟糕。是的,在最简单的情况下(auto x = y),它可以工作,但只要有其他结构,它的行为就会变得更加难以预料。更糟糕的是,错误将更难以发现,因为变量的类型看起来并不是那么明显。幸运的是,对于静态分析工具来说,这并不是问题:它们不会感到疲倦,也不会放松注意力。但对我们来说,作为简单的普通人,最好明确指定类型。我们也可以使用其他方法摆脱这种类型变窄的问题,但我们要在之后的文章里才会谈到这一点。

更多内容请见: http://www.viva64.com/en/b/0429/

栏目导航
上一篇:技术文章翻译(三) – 高效代码审查的一些小技巧
下一篇:技术文章翻译(五) – 利用.NET显示当前屏幕内容

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值