C指针解引用合法内存地址触发段错误的原因排查
问题:C语言指针调试中的解引用崩溃问题
我在调试C语言指针时编写了两段代码:
第一段代码运行后直接退出,错误代码为3221225477:
#include <stdio.h> int main() { int a = 17; int* p1 = &a; int* p2 = (int*)(&p1); p1 = (int*)(&p2); printf("%d\n", *((int*)(*p1))); printf("%d\n", *((int*)(*p2))); return 0; }
第二段代码注释掉解引用的printf语句后,输出正常:
#include <stdio.h> int main() { int a = 17; int* p1 = &a; int* p2 = (int*)(&p1); p1 = (int*)(&p2); printf("&p1 %d\n", &p1); printf("&p2 %d\n", &p2); printf("p1 %d\n", p1); printf("p2 %d\n", p2); printf("*p1 %d\n", *p1); printf("*p2 %d\n", *p2); // printf("%d\n", *((int*)(*p1))); // printf("%d\n", *((int*)(*p2))); return 0; }
输出结果:
&p1 748680992 &p2 748680984 p1 748680984 p2 748680992 *p1 748680992 *p2 748680984
疑问:仅当尝试解引用相关地址时程序失效,明明这些地址之前能正常访问,想了解是否是内存保护机制导致,或是代码写法有误?
问题根源:类型转换错误导致非法内存访问
不是内存保护机制的问题,核心是代码里滥用强制类型转换破坏了指针的类型语义,导致解引用时访问了错误的内存区域:
类型关系混乱:
p1是int*类型,&p1是int**类型(指向指针的指针),但你把它强转成int*赋值给p2;同理&p2是int**,强转成int*赋值给p1。这种转换直接抹掉了指针的层级信息。
解引用的实际行为:
从第二段代码的输出可以看到:*p1的值是&p1的地址,*p2的值是&p2的地址。- 当执行
*((int*)(*p1))时,相当于把&p1这个地址当成int*去解引用——但&p1是指针变量p1的地址,这个地址里存的是p1的值(即&p2的地址),而非合法的int值。 - 更关键的是:多数系统中指针宽度(如64位系统为8字节)和
int宽度(通常4字节)不一致。你把8字节的指针值当成4字节的int地址去解引用,会导致访问的内存地址是指针值的低4字节,这大概率是无效地址或不属于程序的内存区域,直接触发崩溃(错误代码3221225477是Windows下的STATUS_ACCESS_VIOLATION,即非法内存访问)。
正确的写法示例:
如果要实现指针的嵌套,应该遵循类型匹配原则:#include <stdio.h> int main() { int a = 17; int* p1 = &a; int** p2 = &p1; // 使用int**类型,无需强转 printf("%d\n", **p2); // 合法解引用,输出a的值17 return 0; }
总结:代码错误在于强制类型转换破坏了指针的类型层级,导致解引用时访问了错误的内存,和内存保护机制无关。
内容的提问来源于stack exchange,提问作者twowr
相关产品推荐
相关产品推荐

