请指出下面程序运行到哪一行会出错,为什么,请说明原因。
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位系统下,&a.c表示这块内存的起始地址。又有p = &a.c,所以向后访问到p[5]都是安全的。
a.pc = p;
这句也没问题,现在……