指针修改自身

请指出下面程序运行到哪一行会出错,为什么,请说明原因。
C/C++ code

#include <stdio.h>

struct {
    char c;
    char *pc;

}a;

int main() {
    char *p = &a.c;
    p[0] = 0;
    p[1] = 0;
    p[2] = 0;
    p[3] = 0;
    p[4] = 0;
    p[5] = 0;
    a.pc = p;
    a.pc[5] = 0;
    a.pc[4] = 0;
    a.pc[3] = 0;
    a.pc[2] = 0;
    a.pc[1] = 0;
    a.pc[0] = 0;
    return 0;
}



此程序在32为的环境下 用gcc编译运行的时候 是在a.pc[4] = 0; 就出错了。 在64位下,编译运行又没有错误
发现a.pc[5]的地址 与 p[5]的地址是一样的 但打印出来的值却不一样。但不知道为什么?

------解决方案--------------------------------------------------------
仔细想了下,发现这题挺有意思。

两个前提,
1、指针在32位系统是4个字节,在64位系统下是8字节。
2、编译器会对结构体做对齐。c尽管只是一个char,也用了一个指针的长度。

把结构体a看作一块内存的话:
则在32位系统下,&a.c表示这块内存的起始地址。又有p = &a.c,所以向后访问到p[5]都是安全的。
a.pc = p;
这句也没问题,现在a.pc指向a的起始地址。
a.pc[5]=0;
这句就有猫腻了,a.pc[5]就是第5个字节,这个位置在32位系统下恰好就是a.pc本身!
所以这句执行之后,a.pc这个指针的值被篡改了。变成了一个非法地址。
接下来这句
a.pc[4]=0;
就坏事了。pc已经指向一个非法地址,a.pc[4] 相当于 a.pc+4,一样非法。
给它赋值就会造成非法内存访问了。


------解决方案--------------------------------------------------------
探讨

仔细想了下,发现这题挺有意思。

两个前提,
1、指针在32位系统是4个字节,在64位系统下是8字节。
2、编译器会对结构体做对齐。c尽管只是一个char,也用了一个指针的长度。

把结构体a看作一块内存的话:
则在32位系统下,&amp;a.c表示这块内存的起始地址。又有p = &amp;a.c,所以向后访问到p[5]都是安全的。
a.pc = p;
这句也没问题,现在……


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值