温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

C++中为什么不要解引用无效指针

发布时间:2021-11-26 13:42:18 阅读:140 作者:iii 栏目:大数据
C++开发者专用服务器限时活动,0元免费领,库存有限,领完即止! 点击查看>>

本篇内容主要讲解“C++中为什么不要解引用无效指针”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“C++中为什么不要解引用无效指针”吧!

ES.65:不要解引用无效指针

Reason(原因)

解引用例如null等无效指针,是无定义的行为,通常会立即导致程序崩溃,错误的结果,或者内存破坏。

Note(注意)

本规则显而易见而且众所周知,但却很难遵守。它会带来好的代码风格,更充分的库支持,不需要很大代价但可以排除违反的静态解析。这是关于C++类型和资源安全模型的论述的重要组成部分。

See also:(参见)

  • Use RAII to avoid lifetime problems.

  • 使用RAII避免生命周期问题。

  • Use unique_ptr to avoid lifetime problems.

  • 使用unique_ptr避免生命周期问题

  • Use shared_ptr to avoid lifetime problems.

  • 使用shared_ptr避免生命周期问题

  • Use references when nullptr isn't a possibility.

  • 如果不可能出现空指针,使用引用

  • Use not_null to catch unexpected nullptr early.

  • 使用not_null尽早捕获意外的空指针。

  • Use the bounds profile to avoid range errors.

  • 使用边界规则群组避免范围错误。

Example(示例)

void f(){    int x = 0;    int* p = &x;    if (condition()) {        int y = 0;        p = &y;    } // invalidates p    *p = 42;            // BAD, p might be invalid if the branch was taken}

为了解决这个问题,要么扩展对象指针意图指向的对象的生命周期,要么缩短指针的生命周期(将解引用操作移到所指向对象的生命周期结束之前。)

void f1(){    int x = 0;    int* p = &x;    int y = 0;    if (condition()) {        p = &y;    }    *p = 42;            // OK, p points to x or y and both are still in scope}

Unfortunately, most invalid pointer problems are harder to spot and harder to fix.

不幸的是,大多数无效指针问题难于发现,也难于修改。

Example(示例)

void f(int* p){    int x = *p; // BAD: how do we know that p is valid?}

这样的代码大量存在。在经历了大量测试之后,大部分情况下可以动作,但是如果只看局部很难判断一个指针有没有可能为空。因此,空指针也是错误的主要来源之一。存在很多方法可以处理这个潜在问题:

void f1(int* p) // deal with nullptr{    if (!p) {        // deal with nullptr (allocate, return, throw, make p point to something, whatever    }    int x = *p;}

There are two potential problems with testing for nullptr:

检查指针是否为空会有两个潜在问题:

  • it is not always obvious what to do what to do if we find nullptr

  • 在发现了空指针时应该做什么并不总是很明确。

  • the test can be redundant and/or relatively expensive

  • 检查可能是多余的而且/或者代价相当高。

  • it is not obvious if the test is to protect against a violation or part of the required logic.

  • 很难判断这个检查只是为了防止违反还是必要逻辑的一部分。

void f2(int* p) // state that p is not supposed to be nullptr{    assert(p);    int x = *p;}

这种做法只在断言检查有效时需要付出一定的代价,同时可以为编译器/解析器提供有用信息。如果C++得到协议(contracts)的直接支持的话,效果会更好:

void f3(int* p) // state that p is not supposed to be nullptr    [[expects: p]]{    int x = *p;}

Alternatively, we could use gsl::not_null to ensure that p is not the nullptr.

另外,我们可以使用gsl::not_null来保证p不是空指针。

void f(not_null<int*> p){    int x = *p;}

These remedies take care of nullptr only. Remember that there are other ways of getting an invalid pointer.

这个改进只处理空指针。别忘了还有其他形式的无效指针。

Example(示例)

void f(int* p)  // old code, doesn't use owner{    delete p;}void g()        // old code: uses naked new{    auto q = new int{7};    f(q);    int x = *q; // BAD: dereferences invalid pointer}
Example(示例)
void f(){    vector<int> v(10);    int* p = &v[5];    v.push_back(99); // could reallocate v's elements    int x = *p; // BAD: dereferences potentially invalid pointer}
Enforcement(实施建议)

This rule is part of the lifetime safety profile

本规则是生命周期规则群组的一部分

  • Flag a dereference of a pointer that points to an object that has gone out of scope

  • 如果指针指向的对象已经处于生命周期之外,标记它的解引用操作。

  • Flag a dereference of a pointer that may have been invalidated by assigning a nullptr

  • 如果指针由于被设为空指针而无效时,标记它的解引用操作。

  • Flag a dereference of a pointer that may have been invalidated by a delete

  • 如果由于指针指向的对象被销毁而无效时,标记它的解引用操作。

  • Flag a dereference to a pointer to a container element that may have been invalidated by dereference

  • 如果指针指向的容器元素由于解引用而无效时,标记它的解引用操作。

到此,相信大家对“C++中为什么不要解引用无效指针”有了更深的了解,不妨来实际操作一番吧!这里是亿速云网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

原文链接:https://my.oschina.net/u/4579737/blog/4354353

c++
AI

开发者交流群×