指针小问题求解~

来源:百度知道 编辑:UC知道 时间:2024/05/30 08:22:27
void main()
{
char pcmp[7]; int i,j; char *p;
p=pcmp;
for(i=0;i<7;i++) //自己写的
scanf("%d",&pcmp[i]);
for(j=0;j<7;j++)
printf("%d\n",*p++);
}
//#include<stdio.h>

void main()
{
char pcmp[7]; int i,j; char *p;

for(i=0;i<7;i++) //自己改了一遍的
scanf("%d",&pcmp[i]);
p=pcmp;
for(j=0;j<7;j++)
printf("%d\n",*p++);
}

这两个调试没错误,运行有结果,但是为什么运行完了之后会弹出对话框说:应用程序错误“0x0040128c”指令引用的"0x0011ffe4"内存,该内存不能为“written”,要终止程序。
这是怎么回事呢?请好心的高手指点~

哎~scanf总是能产生令人沮丧的问题。
scanf("%d",&pcmp[i]);
对这行的调用中,scanf从stdio中抽取一个整数出来(int型,在某些机器上是4字节,在某些上是2字节),这里不妨假设4字节,它将被存入&pcmp[i]处,当i从0倒5时虽然每次都是写入4字节,但第二次写入总会覆盖前一次的后三个字节,而不会破坏第一个字节,因此6个数没被破坏最后可以正常显示。但i=6时,写入了四字节,最后三个字节是多写入的,虽然第七个数最后也可以正常printf,但为最后的访问违例埋下伏笔。

楼主可以做个实验,输入7个65535看会发生什么事?

继续分析问题,scanf后,printf是正常执行的,直到main函数结束错误还没发生,异常是发生在main函数退出进入_tmainCRTStartup时,因为刚才的溢出多写的三字节覆盖了main函数设置的子ebp,所以返回后_tmainCRTStartup的ebp设置有误,局部变量的参照物ebp是错误的话对各局部变量的引用也指向了难以预测的错误地址,那么如果运气好该地址有写保护则立即发生异常,否则悄无声息的发生错误而无提示是那种最难发现的bug。

这就是著名的缓冲区溢出

所以说scanf最好小心使用。楼主有以下两种方法可以避免出现次错误:
1)char pcmp[7]; int i,j; char *p;
p=pcmp;
改成
int pcmp[7]; int i,j; int *p;
p=pcmp;
这样为pcmp分配的空间为sizeof(int)*7,就不会溢出了

2)scanf("%d",&pcmp[i]);改成scanf("%c",&pcmp[i]);
但如果你的目的是数字输入输出的话,在输出的代码出你还要加上额外的转换代码

printf与scanf不同,printf有所谓的默认类型转换机制。
printf("%d\n",p);句中,p不管是int型还是char型,最终都作为int型进入