崩溃与空指针de-reference,为什么?

时间:2012-12-05 12:43:53

标签: c++

我正在阅读Moai源代码,我很好奇为什么会导致崩溃(或不...)

我真的不明白那个片段。

在档案A:

#define UNUSED(p) (( void )p)

在档案B中:

//----------------------------------------------------------------//
/** @name   crash
    @text   Crashes Moai with a null pointer dereference.

    @out    nil
*/
int MOAISim::_crash ( lua_State* L ) {
    UNUSED(L);

    int *p = NULL;
    (*p) = 0;

    return 0;
}

编辑:

我认为我不理解的部分是" deference"手段。所以,如果你把它放在你的答案中那就太棒了。

3 个答案:

答案 0 :(得分:12)

崩溃是由空指针的取消引用引起的:

(*p) = 0; // <--- Crash

同样如评论中所指出的,UNUSED宏仅用于抑制大多数编译器将提供的“未使用参数”警告。

通常也可以通过简单地不按如下方式指定变量名来阻止警告:

int MOAISim::_crash ( lua_State* ) 
{
    int *p = NULL;
    (*p) = 0;

    return 0;
}

同样值得注意的是,上述情况并非有保障。在其中一个32位控制台上,取消引用空指针实际上导致数字“3”。这确实很难找到空的解引用,但一般来说,如果你看到一个3坐在一个寄存器中,你可能会错误地猜测出了什么问题。

取消引用实质上是要求存储在给定指针处的值。如果指针无效(即指向进程不拥有的内存位置),则会导致崩溃。在Windows中,这称为访问冲突(0xC0000005)。在Linux下,它是一个分段违规,SIGSEGV。

See also

答案 1 :(得分:3)

宏在代码中被替换,因此对于编译器,函数如下所示:

int MOAISim::_crash ( lua_State* L ) {
    (( void )L);

    int *p = NULL;
    (*p) = 0;

    return 0;
}

(( void )L)行评估L并丢弃结果。但是,崩溃不是来自该行,而是来自NULL的{​​{1}}地址的分配。

答案 2 :(得分:1)

int *p = NULL;
(*p) = 0;

第二行是未定义的行为(取消引用nullptr指针)。在您的平台上崩溃应用程序的事实只是一种未定义的行为(在我看来很好,因为你可以更快地捕获bug)。