参考答案:
【问题1】
1、堆栈。2、PUSH和POP。
【问题2】
变量的先后关系、每个变量所占空间、增长方向(数组)
【问题3】
用户输入9个字符的字符串,使其满足条件:前8个字符为任意字符和第9个字符为大写字母A;
【问题4】
缓冲区溢出。对输入参数的长度进行检查;使用安全函数strncpy()来代替strcpy()函数。
详细解析:
【问题1】一个程序在内存中分为程序段、数据段和堆栈三部分。程序段里放着程序的机器码和只读数据;数据段放程序中的静态数据;动态数据则通过堆栈来存放,也就是说,变量存在的内存区域是堆栈;堆栈的特性是后进先出 (LIFO),即先进入堆栈的对象最后出来,最后进入堆栈的对象最先出来。堆栈两个最重要的操作是 PUSH和POP将对象放入堆栈顶端(最外边,内存高端);POP 操作实现一个逆向过程,把顶端的对象取出来。
【问题2】首先根据3个变量定义的先后顺序,buf2先压入堆栈(在最底下),然后是check,最后是buf(最上面);空间大小根据C语言语法即可确定。buf2是16个字节,check是整型变量占用4个字节,buf是字符数组,有8个字符,每个字符占一个字节,共占用8个字节。所以buf、check、buf2三个变量在内存的布局图如下所示:
【问题3】该代码按正常流程走下来,因check的值为1,不满足check==65,所以会执行else语句,所以这道题的关键在于通过什么样的方式来改变check的值,使其等于65,满足条件然后调用Challenge()函数。
再来分析strcpy() 函数这个函数,该用来复制字符串,其原型为:char *strcpy(char *dest, const char *src);
【参数】dest 为目标字符串指针,src 为源字符串指针。
注意:src 和 dest 所指的内存区域不能重叠,且 dest 必须有足够的空间放置 src 所包含的字符串(包含结束符NULL)。
【返回值】成功执行后返回目标数组指针 dest。
strcpy() 把src所指的由NULL结束的字符串复制到dest 所指的数组中,返回指向 dest 字符串的起始地址。
注意:如果参数 dest 所指的内存空间不够大,可能会造成缓冲溢出。
主函数在执行时会接收用户输入信息放入指针数组argv中,而指针数组存放的信息又会通过strcpy复制到buf数组里面,buf数组的长度为8个字符,一旦用户输入数据长度大于8个字符就会溢出,溢出部分就会覆盖其他变量的值,从上面堆栈中的数据存储方式可以看出,buf数组一旦溢出,溢出部分就会覆盖check的值;根据题目意思,只要令溢出部分的值为65即可令check=65,从而满足条件。所以可以先任意输入8个字符堆满buf数组,再输入时就是溢出部分,可以输入大写字母A,因check为整形数据,所以将字符赋给整形变量时,会按其ASCII码值进行处理,即A的ASICC值为65,从而可以把check值变成65满足条件。
【问题4】前面分析strcpy() 函数,当其参数 dest 所指的内存空间不够大,可能会造成缓冲溢出。
而strncpy()用来复制字符串的前n个字符,其原型为:char * strncpy(char *dest, const char *src, size_t n);
【参数说明】dest 为目标字符串指针,src 为源字符串指针。strncpy()会将字符串src前n个字符拷贝到字符串dest。
在编写程序时通常用strncpy()函数来取代strcpy()函数防止缓冲区溢出。