翻译《有关编程、重构及其他的终极问题?》——33.永远不要非法引用空指针

翻译《有关编程、重构及其他的终极问题?》——33.永远不要非法引用空指针

标签(空格分隔):翻译 技术 C/C++
作者:Andrey Karpov
翻译者:顾笑群 - Rafael Gu
最后更新:2018年07月15日


33.永远不要非法引用空指针

这次说的Bug及其相关代码是从GIT源代码中发现的。PVS-Studio分析器对这段代码的诊断结果为:V595 The ‘tree’ pointer was utilized before it was verified against nullptr. Check lines: 134, 136(译者注:大意是说在没有检查tree是否空指针前就使用了)。

void mark_tree_uninteresting(struct tree *tree)
{
  struct object *obj = &tree->object;
  if (!tree)
    return;
  ....
}

解释

毫无疑问,非法引用空指针是一种糟糕的行为,因为其结果是一种未定义行为,我们都了解其背后的理论基础是什么。

但是,在实际写代码时,程序员们就开始争论了。一直有些人觉得上面这段代码可以正确的工作,为了坚持这点他们甚至赌上了他们的一辈子——他们说他们一直这么做的!因此我不得不给出更多的理由来证明我的观点,也希望这篇文章作为另外一个尝试去改变他们的想法。

我特意选择了这个例子来说,就是为了激起更多的讨论。当这个tree指针被非法引用后,其对应对象的成员变量也不是马上就被使用了(译者注:&tree->object中的object就是这个成员变量),只是把这个成员的地址赋值给其他变量了。之后,如果(tree == nullptr),那么这个成员的地址就没有被任何地方使用,而且这个函数也就结束了。所以很多人认为这段代码是正确的。

但并非如此,你不应该写出这样的代码。未定义行为不光是指在空指针处写入值造成程序崩溃之类的情况。未定义行为可能是任何情况。一旦你非法引用了空指针,你就会遇到未定义行为。对于程序后续怎么执行,我们完全无法把握,所以我们也不能进一步去讨论,反正程序就是执行任何它想执行的。

其中一个不可预知的行为就是,编译器可能完全移除“if (!tree) return;”——编译器看到这个指针已经被非法引用了,就可能认为这个指针不为空,编译器就认为对指针的检测语句可以去除。这只是引起程序崩溃众多场景中的一个。

我建议大家可以看下这篇文章,大家可以在其中找到所有与此相关知识的更多细节:http://www.viva64.com/en/b/0306/

正确的代码

void mark_tree_uninteresting(struct tree *tree)
{
  if (!tree)
    return;
  struct object *obj = &tree->object;
  ....
}

建议

请注意未定义行为,即使所有东西看上去工作的很好,根本没有必要去冒险。就如我所说的,很难显现出到底会发生什么。只要避免不可预知情况就好了,即使所有东西工作的很好。

某些人也许认为他确切的知道未定义行为会发生什么,因此他就认为这就可以让他做一些别人不能做的事情,并且他觉得所有东西都可以工作的很好。其实并非curiosity,下一篇我们就会强调未定义行为是非常危险的。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值