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


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

上面指出的指令,我认为应该引起分割错误,但它没有。我尝试通过使用"gcc - 0"来省略默认的编译器优化。

很自然,如果我用int i = pstTemp->a代替它,我得到一个隔离故障。我试图通过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

$3中,我们可以看到,当我试图打印&(pstTemp->a)时,它似乎被解释为一个地址,因此相当于int *p = NULL

然而,我的疑问是,语句(pstTemp->a)不应该在&生效&造成隔离故障?

实际上,甚至不是解引用空指针的行为导致了代码中的未定义行为。

当一个取址操作(&)和一个解引用操作(*->)紧接在一起时,它们会相互抵消并分解成指针运算。因此,表达式&pstTemp->a产生a的地址。

然而,在NULL指针上执行指针算术是未定义的行为。由于没有实际的解引用(并且行为是未定义的),因此编译器似乎没有发出任何明显有害的代码,从而导致分段错误。

不要期望未定义的行为会导致任何特定的错误。它被称为undefined而不是"保证崩溃"是有原因的

这是未定义的行为。

这里不会崩溃,因为没有实际的解引用,我们只取(pstTemp->b)地址,这实际上是b字段的偏移量(最有可能是4,取决于int的大小和编译器)。

试试这个:

typedef struct {
    int a;
    int b;
} stTemp_t;
int main()
{
  stTemp_t *pstTemp = NULL;
  int *p = &(pstTemp->b);
  printf ("%p", p);
  return 0;
}

输出很可能是:

00000004

,

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

很可能崩溃

相关内容

  • 没有找到相关文章

最新更新