是否可能存在引用中的分段错误
Is it possible to have a segmentation fault from a reference?
假设以下代码:
Foo & foo = getFoo();
foo.attr; // 100% safe access?
如果foo
是一个指针,我会检查它是否是NULL
,但因为它是一个引用,所以这样的检查是不必要的。我想知道的是,是否有可能混淆对象的引用,从而使访问其属性变得不安全。
我尝试了一些例子,比如试图将NULL
强制转换为Foo
对象,但我遇到了编译错误。我只想确保上面的代码始终是安全的,并且不存在我应该意识到的可能的内部C++
黑魔法。
根据Benjamin的回答,我可以制作一个示例代码,其中我确实从引用中得到了分段错误,因此它回答了我的问题。我会粘贴我的代码,以防有人对未来感兴趣:
#include <iostream>
using namespace std;
class B
{
public:
int x;
B() {x = 5;}
};
class A
{
public:
void f()
{
b = *(B*)NULL;
}
B & getB()
{
return b;
}
B b;
};
int main()
{
A a;
a.f();
cout << a.getB().x << endl;
return 0;
}
是的,这是可能的。
Foo& Fr = *(Foo*)nullptr;
从技术上讲,这已经是未定义的取消引用该指针的行为。但它很可能不会导致任何可观察到的误差。这可能会:
Fr.attr = 10;
然而,正如Jonathan Wakely在评论中指出的那样,你没有理由检查这样的案例。如果函数返回无效引用,则该函数已损坏,需要修复。您的使用代码并没有因为假设引用有效而被破坏。然而,正如David Schwartz的回答中所提到的,在完全合法的代码中,有效的引用可以变得无效(尽管不是null)。但是你没有办法检查这个。你只需要知道在什么情况下会发生这种情况,然后停止使用引用。
当引用位于某个有效对象时,该引用必须引用该对象。这是一个C++标准要求,任何违反它的代码都是UB(未定义的行为),可以做任何事情。
然而,在引用所在之后销毁引用引用的对象是完全合法的。在这一点上,访问引用是非法的。例如:
std::vector<int> j;
j.push_back(3);
int& k = j.front(); // legal, object exists now
j.clear(); // legal, object may be destroyed while reference exists
k++; // illegal, destruction of object invalidates reference
这意味着返回引用的函数必须始终返回在返回时有效的引用。这就是为什么在空向量上调用front
是UB的原因——引用在就位时必须有效。然而,通常会有一些条件会导致该引用无效,如果您计划隐藏该引用并稍后访问它,则需要了解这些条件是什么。
通常,您应该假设将返回的引用隐藏起来并稍后访问它是不安全的,除非您知道该引用仍然有效。例如,std::vector
仔细解释了在什么条件下可以使对容器的引用无效,这包括对push_back
的后续调用。所以这个坏了:
std::vector<int> j;
j.push_back(3);
int &first = j.front();
j.push_back(4);
int &second = j.back();
if (first == second) // illegal, references into container are invalidated by push_back
但这很好:
std::vector<int> j;
j.push_back(3);
j.push_back(4);
int &first = j.front();
int &second = j.back();
if (first == second) // legal, references into container stay valid
可能存在对坏内存的引用。所以foo.attr; // 100% safe access?
的答案是否定的。考虑下面的例子:
int &something() {
int i = 5, &j = i;
return j; // Return reference to local variable. This is destroyed at end of scope.
}
int main() {
int &k = something(); // Equivalent to getFoo()
std::cout << k << endl; // Using this reference is undefined behavior.
return 0;
}
活生生的例子。
引用k没有指向合法内存。但这仍然会编译。然而,在程序员没有犯错误的情况下,这种情况是不可能发生的。在这种情况下,函数something()
写入错误,需要进行修复。没有办法,也没有理由对此进行检查。如果一个函数返回了一个错误的引用,那么你唯一能(也应该)做的就是修复有问题的函数。
- 在某些循环内使用vector.push_back时出现分段错误
- 为什么在运行时没有向我们提供有关分段错误的更多信息?
- 如何解决gcc编译器优化导致的centos双编译器设置中的分段错误
- 当我的阵列太大时出现分段错误
- 分段错误当我试图运行程序时出错
- 在c++中初始化矩阵时出现分段错误(核心转储)
- 尝试使用集合函数时出现分段错误
- 我无法缩小此分段错误的原因
- g++的分段错误(在NaN上使用to_string两次时)
- 我是如何在这段代码中出现分段错误的
- 创建结构的数组时遇到分段错误
- 在c++中键入向量中的所有值后,得到分段错误(核心转储)
- 在 c++ 中实现 Trie 时出现分段错误
- 为什么 fstream 在打开带有格式的文件时会导致分段错误?
- 为什么我遇到分段错误?
- 动态类的分段错误(家庭作业问题)
- 分段错误 - 读取初始化指针的数组
- 如何摆脱C ++中的分段错误错误?
- 使用 CTYPE 时出现分段错误
- 为什么代码给出分段错误?