指针应用小结(一)

指针是C/C++中最灵活的变量,可随意指向任何内存地址,稍有不慎,就会造成程序崩溃,且很难找出原因。

下面这道题,程序crash,一开始没找到原因,经过gdb调试之后,找到根本原因。

struct sInt
{
  int i;
  int *p;
};
//在64位环境下,sizeof(sInt) = 8; 其中 i占4个字节,p占8个字节,为了保证字节对齐,编译器对i之后地址补齐(加上int padding,占4个字节),共16字节
//8字节对齐是为了提高CPU对数据的读取效率
int test_sInt()
{
  sInt s;
  int *p=&s.i;
  p[0]=0;
  p[1]=1;
  p[2]=2;
  p[3]=3;
  s.p=p;   //s.p指向s.i的地址
  s.p[0]=0;//对s.i赋值
  s.p[1]=1;//对padding赋值
  s.p[2]=2; //对s.p赋值,s.p指针将“飞走”,指向一个非法地址
  s.p[3]=3;//对一个非法地址赋值,Segmentation fault
  return 0;
} 

//下面对程序做了下扩展测试,如果i,p为2个局部变量,程序一样crash。
int test_int()
{
  int i;
  int *p;
  i = 0;
  p = &i;
  p[0]=0;
  p[1]=1;
  p[2]=2;//i,p不属于结构体,不用8字节对齐,所以在p[1]赋值时,指针p就"飞走了",p[2]为非法内存,Segmentation fault
  p[3]=3;
  return 0;
} 

//如果结构体中成员变量为char,程序不一定会crash。
//这是因为char *p 占8个字节,p[8]赋值改变1个字节的内容,指针“飞”的很近,可能在合法范围内,所以不一定会crash;
//     而int *p也占8个字节,p[2]赋值将会改变4个字节的内容,指针“飞”跑了,逃出合法范围,必将crash.
struct sChar
{
  char i;
  char *p;
};

int test_sChar()
{
  sChar s;
  char *p=&s.i;
  for(int i = 0; i<16; i++)
  {
    p[i] = 'a'; 
  } 

 s.p=p;
  for(int i = 0; i<16; i++)
  {
    s.p[i] = 'a'; //i>8时,随机Segmentation fault
  }  
 return 0;
} 

int main()
{
  test_sInt();
  test_int(); 
  test_sChar();
  return 1;
}


 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值