为什么简单地取消引用指定NULL的指针不会崩溃

时间:2016-04-27 09:11:18

标签: c++ undefined-behavior

 #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;
 }

在上面的代码中,当我评论&#34; Point-2&#34;代码没有崩溃。 但是,当我取消评论&#34; Point-2&#34;它崩溃了。 由于ptr理想情况下为NULL,因此Point-1也应该崩溃。如果我错了,请纠正我。 有人可以解释一下为什么代码没有崩溃当我简单地解除指针?

2 个答案:

答案 0 :(得分:2)

取消引用空指针是未定义的行为。未定义的行为不等于错误。如果触发未定义的行为,可能会发生任何事情。如果你问另一种方式:

  

为什么未定义的行为不会导致错误而不是给我们奇怪的行为?

可能是由于很多原因。一个原因是表现。例如,在std::vector的实现中(至少在MSVC中),在发布模式下不检查索引是否超出范围。您可以尝试这样做:

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;
}

我想你现在明白了。

答案 1 :(得分:0)

在第2点,您尝试显示0x0地址的内容,这会产生访问冲突错误。

在第1点中,您不执行任何操作,因此程序不必访问此指针所描述的内存。这不会产生访问冲突错误。