为什么简单地取消引用分配了 NULL 的指针不会崩溃
Why Simply de-referencing a pointer with NULL assigned is not crashing
#include <iostream>
int main()
{
int *ptr = NULL;
// It does not crash
*ptr; --------> Point-1
//But this statment crashed
std::cout<<"Null:"<<*ptr<<"\n"; ------> Point-2
return 0;
}
在上面的代码中,当我评论 "Point-2" 时代码没有崩溃。
但是,当我取消对 "Point-2" 的注释时,它崩溃了。
由于 ptr 是 NULL 理想情况下 Point-1 也应该崩溃。如果我错了,请纠正我。
有人能解释一下为什么当我简单地取消引用指针时代码没有崩溃吗?
取消引用空指针是未定义的行为。未定义的行为不等于错误。如果你触发了未定义的行为,任何事情都可能发生。如果你问的是另一种方式:
Why is undefined behavior not causing an error instead of giving us strange behavior?
可能有很多原因。原因之一是性能。例如,在 std::vector
的实现中(至少在 MSVC 中),在 Release Mode 中没有检查索引是否 out of range。您可以尝试这样做:
std::vector<int> v(4);
v[4]=0;
它将编译并运行。你可能会有奇怪的行为,也可能不会。但是,在调试模式下,它会在 运行 时抛出异常。 MSVC 在调试模式下进行检查,因为在调试模式下性能并不重要。但它不在发布模式下,因为性能很重要。
这同样适用于取消引用空指针。您可以想象取消引用的代码将像这样放在包装器中:
//Imaginary code
T& dereference(T* ptr){
if(ptr==nullptr){
throw;
}
return *ptr;
}
这部分:if(ptr==nullptr){throw;}
将减慢上下文中每个指针的取消引用过程,这是不可取的。
不过,也可以这样做:
//Imaginary code
T& dereference(T* ptr){
#ifdef DEBUG
if(ptr==nullptr){
throw;
}
#endif
return *ptr;
}
我想你现在明白了。
在第 2 点中,您尝试显示 0x0 地址的内容,这会产生访问冲突错误。
在第 1 点中,您什么都不做,因此程序不必访问该指针所描述的内存。这不会产生访问冲突错误。
#include <iostream>
int main()
{
int *ptr = NULL;
// It does not crash
*ptr; --------> Point-1
//But this statment crashed
std::cout<<"Null:"<<*ptr<<"\n"; ------> Point-2
return 0;
}
在上面的代码中,当我评论 "Point-2" 时代码没有崩溃。 但是,当我取消对 "Point-2" 的注释时,它崩溃了。 由于 ptr 是 NULL 理想情况下 Point-1 也应该崩溃。如果我错了,请纠正我。 有人能解释一下为什么当我简单地取消引用指针时代码没有崩溃吗?
取消引用空指针是未定义的行为。未定义的行为不等于错误。如果你触发了未定义的行为,任何事情都可能发生。如果你问的是另一种方式:
Why is undefined behavior not causing an error instead of giving us strange behavior?
可能有很多原因。原因之一是性能。例如,在 std::vector
的实现中(至少在 MSVC 中),在 Release Mode 中没有检查索引是否 out of range。您可以尝试这样做:
std::vector<int> v(4);
v[4]=0;
它将编译并运行。你可能会有奇怪的行为,也可能不会。但是,在调试模式下,它会在 运行 时抛出异常。 MSVC 在调试模式下进行检查,因为在调试模式下性能并不重要。但它不在发布模式下,因为性能很重要。
这同样适用于取消引用空指针。您可以想象取消引用的代码将像这样放在包装器中:
//Imaginary code
T& dereference(T* ptr){
if(ptr==nullptr){
throw;
}
return *ptr;
}
这部分:if(ptr==nullptr){throw;}
将减慢上下文中每个指针的取消引用过程,这是不可取的。
不过,也可以这样做:
//Imaginary code
T& dereference(T* ptr){
#ifdef DEBUG
if(ptr==nullptr){
throw;
}
#endif
return *ptr;
}
我想你现在明白了。
在第 2 点中,您尝试显示 0x0 地址的内容,这会产生访问冲突错误。
在第 1 点中,您什么都不做,因此程序不必访问该指针所描述的内存。这不会产生访问冲突错误。