You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

修改后续内存位置值时指针变量值异常变化的原因排查

指针变量a意外修改及段错误的原因分析

问题复现

第一段代码

int *a, *b,*c,d;
a=&d;
printf("1 a=%p &d=%p\n", a,&d);
b=a+1;
printf("2 a=%p &d=%p b=%p\n", a,&d,b);
c=a+2;
printf("3 a=%p &d=%p b=%p c=%p\n", a, &d,b,c);
*b=34;
printf("4 a=%p &d=%p b=%p c=%p\n", a, &d,b,c);
d=342;
printf("5 a=%p &d=%p b=%p c=%p\n", a, &d,b,c);
*c=21;
printf("6 a=%p &d=%p b=%p c=%p\n", a, &d,b,c);
*b=37;
printf("7 a=%p &d=%p b=%p c=%p\n", a, &d,b,c);
*c=29;
printf("8 a=%p &d=%p b=%p c=%p\n", a, &d,b,c);

实际输出:

1 a=0x7ffd0267145c &d=0x7ffd0267145c

2 a=0x7ffd0267145c &d=0x7ffd0267145c b=0x7ffd02671460

3 a=0x7ffd0267145c &d=0x7ffd0267145c b=0x7ffd02671460 c=0x7ffd02671464

4 a=0x7ffd00000022 &d=0x7ffd0267145c b=0x7ffd02671460 c=0x7ffd02671464

5 a=0x7ffd00000022 &d=0x7ffd0267145c b=0x7ffd02671460 c=0x7ffd02671464

6 a=0x1500000022 &d=0x7ffd0267145c b=0x7ffd02671460 c=0x7ffd02671464

7 a=0x1500000025 &d=0x7ffd0267145c b=0x7ffd02671460 c=0x7ffd02671464

8 a=0x1d00000025 &d=0x7ffd0267145c b=0x7ffd02671460 c=0x7ffd02671464

第二段修改后的代码

int *a, *b,*c,d;
a=&d;
printf("1 a=%p &d=%p\n", a,&d);
b=a+4;
printf("2 a=%p &d=%p b=%p\n", a,&d,b);
c=a+8;
printf("3 a=%p &d=%p b=%p c=%p\n", a, &d,b,c);
*b=34;
printf("4 a=%p &d=%p b=%p c=%p\n", a, &d,b,c);
d=342;
printf("5 a=%p &d=%p b=%p c=%p\n", a, &d,b,c);
*c=21;
printf("6 a=%p &d=%p b=%p c=%p\n", a, &d,b,c);
*b=37;
printf("7 a=%p &d=%p b=%p c=%p\n", a, &d,b,c);
*c=29;
printf("8 a=%p &d=%p b=%p c=%p\n", a, &d,b,c);
return 0;

实际输出:

1 a=0x7ffc674b76dc &d=0x7ffc674b76dc

2 a=0x7ffc674b76dc &d=0x7ffc674b76dc b=0x7ffc674b76ec

3 a=0x7ffc674b76dc &d=0x7ffc674b76dc b=0x7ffc674b76ec c=0x7ffc674b76fc

4 a=0x7ffc674b76dc &d=0x7ffc674b76dc b=0x22674b76ec c=0x7ffc674b76fc

5 a=0x7ffc674b76dc &d=0x7ffc674b76dc b=0x22674b76ec c=0x7ffc674b76fc

6 a=0x7ffc674b76dc &d=0x7ffc674b76dc b=0x22674b76ec c=0x7ffc674b76fc

Segmentation fault (core dumped)

原因分析

两个问题的本质都是栈内存越界访问引发的未定义行为,具体细节如下:

1. 第一段代码中a被意外修改的逻辑

C语言中,局部变量(a、b、c、d)都存储在栈上,栈通常从高地址向低地址生长。从输出反推,你的栈布局中,d的内存地址之后(高地址方向)恰好是指针变量a的存储位置:

  • a是int*类型,值为&d(0x7ffd0267145c);执行b=a+1时,因为a是int*,指针加法会自动偏移sizeof(int)(4字节),所以b指向0x7ffd02671460——这个地址正好是a变量自身的存储地址。
  • 当执行*b=34时,相当于直接修改a变量的内存内容:把a原本存储的&d(0x7ffd0267145c)覆盖为34(十六进制0x22),结合栈地址的高位数据,最终a的值变成0x7ffd00000022。
  • 后续c=a+2指向&d + 2*sizeof(int),也就是a变量存储地址的下一个4字节区域,修改*c会继续篡改a的高位字节,导致a的值持续异常。

2. 第二段代码触发段错误的逻辑

修改后b=a+4指向&d + 16字节,c=a+8指向&d +32字节:

  • 初始*b=34修改的是栈上的某个有效区域,仅破坏了局部变量b自身的值(输出中b变为0x22674b76ec),未触发直接错误。
  • 执行*c=21时,c指向的地址已经超出当前栈帧的有效范围,访问了不属于当前进程的内存,或者触发了栈保护机制(如金丝雀值检查),直接引发段错误。

核心本质

C语言不做指针访问的边界检查,当指针访问超出目标变量所属内存范围的地址时,属于未定义行为——可能修改其他变量、破坏栈帧、触发段错误,甚至出现无规律的诡异行为。你的代码中,b、c均指向d变量之外的栈内存,恰好覆盖了其他局部变量或栈关键数据,从而引发异常。


内容的提问来源于stack exchange,提问作者Gurjot Singh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 11:35:55