温馨提示×

温馨提示×

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

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

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

发布时间:2021-11-26 13:42:18 来源:亿速云 阅读:127 作者:iii 栏目:大数据

本篇内容主要讲解“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++中为什么不要解引用无效指针”有了更深的了解,不妨来实际操作一番吧!这里是亿速云网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

向AI问一下细节

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

c++
AI