简体   繁体   English

通过空结构指针取消引用变量地址,没有分段错误

[英]dereference variable address through null structure pointer, no segmentation fault

typedef struct {
    int a;
}stTemp_t;

int main()
{
stTemp_t *pstTemp = NULL;
int *p = &(pstTemp->a);       // <<----- supposedly de-ref NULL pointer

return 0;
}

The instruction pointed above, i thought should've caused a segmentation fault which it does not. 上面指出的指令,我认为应该引起一个它没有的分段错误。 I tried omitting the default compiler optimization by using "gcc -O0". 我尝试使用“gcc -O0”省略默认的编译器优化。

Naturally enough, if I replace that with int i = pstTemp->a , I get a seg-fault. 当然,如果我用int i = pstTemp->a替换它,我会得到一个seg-fault。 I tried to run the above program throgh gdb to figure out what is going on & following is my observation - 我试图运行上面的程序throgh gdb来弄清楚发生了什么,以下是我的观察 -

(gdb) p pstTemp
$2 = (stTemp_t *) 0x0
(gdb) p pstTemp->a
Cannot access memory at address 0x0
(gdb) p &(pstTemp->a)
$3 = (int *) 0x0

here in $3 , we can see that when i try to print &(pstTemp->a) , it seems to be interpreted as an address hence being equivalent to int *p = NULL . $3 ,我们可以看到当我尝试打印&(pstTemp->a) ,它似乎被解释为一个地址,因此相当于int *p = NULL

However my doubt is, shouldn't the statement (pstTemp->a) get evaluated before the & takes effect & cause a seg-fault anyways? 但是我怀疑的是,在&生效之前是否应该对语句(pstTemp->a)进行评估并导致seg-fault?

Actually, it's not even the act of dereferencing the null pointer that's causing undefined behavior in your code. 实际上,它甚至不是解除引用代码中导致未定义行为的空指针的行为。

When an address-of ( & ) and a dereference ( * or -> ) operation follow each other immediately, then they cancel each other and collapse into pointer arithmetic. 当地址( & )和解除引用( *-> )操作立即相互跟随时,它们相互抵消并折叠成指针算术。 Thus, the expression &pstTemp->a yields the address of a . 因此,表达&pstTemp->a产生的地址a

However, performing pointer arithmetic on a NULL pointer is undefined behavior. 但是, 对NULL指针执行指针运算是未定义的行为。 Since no actual dereferencing done (and the behavior is undefined anyways), it seems the compiler just didn't emit any apparently harmful code that would caused a segmentation fault. 由于没有进行实际的解除引用(并且行为未定义),编译器似乎没有发出任何会导致分段错误的明显有害的代码。

Don't expect undefined behavior to result in any particular error. 不要指望未定义的行为会导致任何特定错误。 It's called undefined and not "guaranteed crash" for a reason. 它被称为未定义而不是“保证崩溃” 的原因。

It's undefined behaviour. 这是未定义的行为。

It doesn't crash here, because there is no actual dereferencement, we only take the address of (pstTemp->b) which is actually the offset of the b field (most likely 4, depending on the size of int and the compiler). 它不会在这里崩溃,因为没有实际的解引用,我们只取(pstTemp->b)地址 ,这实际上是b字段的偏移量(最可能是4,取决于int和编译器的大小) 。

Try this: 尝试这个:

typedef struct {
    int a;
    int b;
} stTemp_t;

int main()
{
  stTemp_t *pstTemp = NULL;
  int *p = &(pstTemp->b);

  printf ("%p", p);
  return 0;
}

Te output will most likely be: Te输出很可能是:

00000004

But

   printf ("%d", pstTemp->b);

will most likely crash. 很可能会崩溃。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM