一道google笔试题的简单分析

  这是2012年9月24日google的笔试题目(大意):

#include <stdio.h>


char* fun()
{
    char X[100];
    sprintf(X, "Hello World!");
    return X+6;
}

int main()
{
    printf("%s", fun());
    return 0;
}

  对于上面的程序,会不会崩溃,如果不会崩溃,那么会输出什么? 【可选项大致有1)一定会崩溃 2)可能会崩溃,输出World 3)、、、忘了】

  对这道题目我进行分析下:

  1.首先,fun返回的是一个指针,即fun函数局部变量X的地址+6,而main函数中是要以字符串形式输出X+6开始地址上的数据;

  2.我们知道X[100]是分配在栈上的空间,在函数返回时,局部数据将会被”清除“;由于栈上空间的分配是线性分配,具体来说就是从高地址向低地址分配,ESP指向栈顶,即栈空间的分配和释放是通过减小或增大ESP的值来实现。那么在释放局部数据X[100]时,实际上只是简单对ESP实施了加100的偏移实现,而对数据并未进行任何操作,即原来数据仍然在栈上,只不过不在EBP和ESP之内。这也就是为什么前面的“清除”要加引号的缘故。因此即使函数返回,但访问X+6仍然可以指向字符串“World”,是不是因此最后输出的就是World呢?实际测试,不是!!

  3. 在函数返回后,访问X+6,实际上该地址是栈上的地址,但并非介于ebp和esp内,并且处于esp的低地址方向,即该地址可以再次被分配利用。

  4. printf("%s",X+6)时,X+6仍然指向World。那么输出为什么不是World呢?通过跟踪printf发现,由于printf函数需要大量的栈空间,所以X+6指向的地方被再次利用,原来的数据被覆盖了!!所以输出不是World(注:Win下测试,输出空;Mac下测试输出sionq)。那么输出什么呢?不确定,取决于printf函数的实现。在考场上可能没时间调试,故不确定输出什么。

  5.      关于崩溃,姑且认为是不可能的。   因为x是个有效地址,所以X+6必然也是个有效的地址,故不存访问地址出错,故不崩溃。

 

总结一下:首先,输出是不确定的,取决于printf函数内部对栈空间的使用,再者程序一定不会崩溃。

                                                                                                                                                                                                

posted on 2012-09-25 01:24  rainduck  阅读(508)  评论(0编辑  收藏  举报

导航