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

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

疑问:仅当尝试解引用相关地址时程序失效,明明这些地址之前能正常访问,想了解是否是内存保护机制导致,或是代码写法有误?


问题根源:类型转换错误导致非法内存访问

不是内存保护机制的问题,核心是代码里滥用强制类型转换破坏了指针的类型语义,导致解引用时访问了错误的内存区域:

  1. 类型关系混乱:

    • p1是int*类型,&p1是int**类型(指向指针的指针),但你把它强转成int*赋值给p2;同理&p2是int**,强转成int*赋值给p1。这种转换直接抹掉了指针的层级信息。
  2. 解引用的实际行为:
    从第二段代码的输出可以看到:

    • *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,即非法内存访问)。
  3. 正确的写法示例:
    如果要实现指针的嵌套,应该遵循类型匹配原则:

    #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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 12:25:18