• 一道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函数内部对栈空间的使用,再者程序一定不会崩溃。

                                                                                                                                                                                                    

  • 相关阅读:
    Spring Controller 获取请求参数的几种方法
    JSP ajax跨域问题 怎么处理 原因:CORS 头缺少 'Access-Control-Allow-Origin')。 ajax http 415
    仿微信滑动返回
    App重新启动
    NetWorkUtils
    ProgressWheel
    没有系统头部的dialog
    仿微信添加触摸图片阴影效果
    循环滚动TextView
    java 分割字符串后放入List中
  • 原文地址:https://www.cnblogs.com/rainduck/p/2700937.html
Copyright © 2020-2023  润新知