访问值为 Null 的指针和访问它指向的对象之间有什么区别?
What is the Difference between accessing a Pointer whose value is Null and accessing what it points to?
我听说访问值为 null 的指针是安全的,因为您没有向它设置任何数据或从它设置任何数据,您只是在访问它。
但我也听说访问它指向的内容(当它为 null 时)不安全,这是为什么呢?
如果您正在访问它指向的内容(当它为 null 时),您不是什么都没有访问吗?
我认为应该不会有任何问题,除非您从中设置值。
我从很多人那里听说我从未经历过任何与此相关的崩溃或错误(当从空指针内部读取数据时),当我捕获到异常时我只是让这是因为我没有将它的任何数据设置为某些东西。可以吗?
int x;
int* px = &x;
int* pn = nullptr;
if (px==px) { do something;}
By accessing I mean dereferencing
取消引用空指针是未定义的行为。
I never experienced any crashes or bugs related to that
该程序有未定义的行为,这意味着它仍然存在错误,即使它没有明确说明并且“似乎正在运行”。
Undefined behavior means anything1 can happen including but not limited to the program giving your expected output. But never rely(or make conclusions based) on the output of a program that has undefined behavior. The program may just crash.
所以您看到(也许看到)的输出是未定义行为的结果。正如我所说,不要依赖具有 UB 的程序的输出。程序可能会崩溃。
因此,使程序正确的第一步是删除 UB。 然后并且只有那时你可以开始对程序的输出进行推理。
1有关未定义行为的更准确的技术定义,请参阅 this 其中提到:没有对程序行为的限制.
示例代码(此时由 OP 公开)有点混乱。
因此,我想在 允许和不允许的情况下添加一些示例:
#include <iostream>
int main()
{
int x = 0; // make some storage
int* px = &x; // px initalized with address of x -> OK.
int* pn = nullptr; // pn initialized with nullptr -> OK.
if (px == px) { /* ... */ } // senseless but -> OK.
if (px == pn) { /* ... */ } // -> OK.
std::cout << *px; // dereference a valid pointer -> OK.
std::cout << *pn; // dereference a null pointer -> UNDEFINED BEHAVIOR!
px = pn; // assign a (null) pointer -> OK.
std::cout << *px; // dereference a null pointer -> UNDEFINED BEHAVIOR!
// ...and finally a common bug...
int* py = nullptr; // -> OK.
{ int y = 1; // storage with limited life-time -> OK.
py = &y; // assign address of storage -> OK.
} // scope end -> life-time of y ends -> OK.
// Attention! This makes py dangling (pointing to released storage).
if (py /* != nullptr*/) { // This doesn't help. py is not a null pointer.
std::cout << *py; // access after end of life-time -> UNDEFINED BEHAVIOR!
}
}
编译器 (g++ 11.2) 的输出:
g++ -std=c++17 -O2 -Wall -pedantic -pthread main.cpp # && ./a.out # Compile but don't exec. It contains UNDEFINED BEHAVIOR!
main.cpp: In function 'int main()':
main.cpp:8:10: warning: self-comparison always evaluates to true [-Wtautological-compare]
8 | if (px == px) { /* ... */ } // senseless but -> OK.
| ~~ ^~ ~~
我听说访问值为 null 的指针是安全的,因为您没有向它设置任何数据或从它设置任何数据,您只是在访问它。
但我也听说访问它指向的内容(当它为 null 时)不安全,这是为什么呢?
如果您正在访问它指向的内容(当它为 null 时),您不是什么都没有访问吗?
我认为应该不会有任何问题,除非您从中设置值。
我从很多人那里听说我从未经历过任何与此相关的崩溃或错误(当从空指针内部读取数据时),当我捕获到异常时我只是让这是因为我没有将它的任何数据设置为某些东西。可以吗?
int x;
int* px = &x;
int* pn = nullptr;
if (px==px) { do something;}
By accessing I mean dereferencing
取消引用空指针是未定义的行为。
I never experienced any crashes or bugs related to that
该程序有未定义的行为,这意味着它仍然存在错误,即使它没有明确说明并且“似乎正在运行”。
Undefined behavior means anything1 can happen including but not limited to the program giving your expected output. But never rely(or make conclusions based) on the output of a program that has undefined behavior. The program may just crash.
所以您看到(也许看到)的输出是未定义行为的结果。正如我所说,不要依赖具有 UB 的程序的输出。程序可能会崩溃。
因此,使程序正确的第一步是删除 UB。 然后并且只有那时你可以开始对程序的输出进行推理。
1有关未定义行为的更准确的技术定义,请参阅 this 其中提到:没有对程序行为的限制.
示例代码(此时由 OP 公开)有点混乱。
因此,我想在
#include <iostream>
int main()
{
int x = 0; // make some storage
int* px = &x; // px initalized with address of x -> OK.
int* pn = nullptr; // pn initialized with nullptr -> OK.
if (px == px) { /* ... */ } // senseless but -> OK.
if (px == pn) { /* ... */ } // -> OK.
std::cout << *px; // dereference a valid pointer -> OK.
std::cout << *pn; // dereference a null pointer -> UNDEFINED BEHAVIOR!
px = pn; // assign a (null) pointer -> OK.
std::cout << *px; // dereference a null pointer -> UNDEFINED BEHAVIOR!
// ...and finally a common bug...
int* py = nullptr; // -> OK.
{ int y = 1; // storage with limited life-time -> OK.
py = &y; // assign address of storage -> OK.
} // scope end -> life-time of y ends -> OK.
// Attention! This makes py dangling (pointing to released storage).
if (py /* != nullptr*/) { // This doesn't help. py is not a null pointer.
std::cout << *py; // access after end of life-time -> UNDEFINED BEHAVIOR!
}
}
编译器 (g++ 11.2) 的输出:
g++ -std=c++17 -O2 -Wall -pedantic -pthread main.cpp # && ./a.out # Compile but don't exec. It contains UNDEFINED BEHAVIOR!
main.cpp: In function 'int main()':
main.cpp:8:10: warning: self-comparison always evaluates to true [-Wtautological-compare]
8 | if (px == px) { /* ... */ } // senseless but -> OK.
| ~~ ^~ ~~