首页 | 编程语言 | 网站建设 | 游戏天堂 | 冲浪宝典 | 网络安全 | 操作系统 | 软件时空 | 硬件指南 | 病毒相关 | IT 认证
软讯网络 > 编程语言 > C/C++ > 比较难的面试题
【标  题】:比较难的面试题
【关键字】:
【来  源】:http://blog.csdn.net/jianxiong8814/archive/2007/04/11/1560333.aspx

比较难的面试题

问:
如果你要为客户写一个函数(软件开发客户),该函数用来处理一个数组
入口是这样的void test(int *p)
在函数中将要对该数组进行操作,情况有2种:
1   送入的数组是静态分配的
2   送入的数组是动态分配(如MALLOC)的
那如何去判断这两种分配情况呢

wanguodu(足文字D)的答案:

不谦虚的说,我觉得我已经给出了答案。
    至于说,用_msize函数,这个是VC的专利,其它弊端前面已经讨论得很清楚了。用free?当它释放非动态分配的内存还有栈上分配的内存时会抛出异常,而且显然不能区分静态内存和栈内存。用汇编取得ebp和esp,借此判断是否是栈内存是可以的,但怎么区分是静态内存还是堆内存呢?
    综上所述,利用各编译器处理变量和动态内存分配的公共策略,那就是分块处理,是最切实可行的办法。相信有经验的C/C++开发人员都不会否认以下事实:
    1、编译器总是把程序中的静态变量集中分配在内存的低端,一般包括DATA区和BSS区。DATA区集中存放已初始化的全局变量。BSS区集中存放未初始化的全局变量,而且BSS区在可执行文件中只存放(相对)起始地址和长度信息以节省外存空间,只有在装入内存的时候才展开并全部初始化为0;
    2、运行进程的地址空间布局:不考虑环境区、命令行参数以及代码区,按地址从低到高依次为静态区(包括DATA区和BSS区)+ 堆 + 栈。堆和栈共用进程的一大段高地址内存,分别用于存放程序动态分配的内存(比如malloc)和运行函数调用堆栈(其中包括当前函数的局部变量,返回地址,一些保存寄存器值等),但是堆的内存分配方式为为从低到高增长,而栈却是从高到低增长。
    有了这种分析之后,我们不难得出如下结论“因为各种内存,无论是静态内存,动态分配的内存还是堆栈,它们分别都是成块集中存放的,相互之间没有交叉,所以对于任一个给定的合法内存地址p来说,它和同类地址a1之间的距离与它和异类内存地址a2之间的距离相比,总有下式成立:
               |p-a1| < |p-a2|.
    有了这个结论,我们就可以认为设置三个分别位于静态区、堆和栈中的变量,通过它们的地址分别与用户传入的地址(比如q)进行比较,其中离q最近的那个变量所在的区块也就是q所在的区块,以此判断q是静态分配的,动态分配的还是局部数组。具体程序我已经在前面的文章中给出,这里稍加整理后再贴一遍以方便各位大佬阅读:

#include <stdio.h>
#include <stdlib.h>

#define SMALLER(a, b)   ((a)>(b) ? (b) : (a))
#define MIN(a, b, c)    SMALLER(SMALLER(a,b), c)
#define ABS(x)          ((x) < 0 ? -(x) : (x))

void test(int *p)
{
         int x;                           /* x位于栈中 */
         static int y = 1;                /* y位于静态区中 */
         static int *q = malloc(sizeof(int)); /* q所指向的内存位于堆中, q定义为static的是为了只malloc一次,否则容易造成内存碎片 */

         unsigned int u = ABS((unsigned int)q-(unsigned int)p);     /* 计算q与p间距离 */
         unsigned int v = ABS((unsigned int)&x-(unsigned int)p);    /* 计算q与&x间距离 */
         unsigned int w = ABS((unsigned int)&y-(unsigned int)p);    /* 计算q与&y间距离 */
         unsigned int s = MIN(u, v, w);                             /* 求最小距离 */

         if(p == NULL)                      /* sanity check */
         {
               printf("test() in file %s: NULL pointer parameter.\n", __FILE__);
               return ;
         }

         if(s == u)
         {
               printf("p located in heap.\n");  /* 与q最近,故p所指内存在堆中 */
         }
         else if(s == v)
         {
               printf("p located in stack.\n");  /* 与&x最近,故p所指内存在栈中 */
         }
         else
         {
               printf("p located in data section.\n");  /* 与&y最近,故p所指内存是静态分配的*/
         }
        
}

int a[100] = {1};                

int main(void)
{
    int *b = (int *)malloc(100);
    int c[100];

    test(a);          /* 测试静态内存 */
    test(b);          /* 测试动态内存 */
    test(c);          /* 测试栈内存 */

    free(b);

    return 0;
}

 
如何不让Doc/View框架不创建新文档:【上一篇】
[全]heapalloc,globalalloc,virtualalloc,new的异同:【下一篇】
【相关文章】
没有相关文章
【随机文章】
  • About SpringMVC ! other
  • 浅谈Linux 优化及安全配置的个人体会
  • Jboss-seam --> page2
  • Linux可卸载内核模块完全指南(二)
  • QQ聊天场景的简单制作技巧(2)
  • Why use Store procedure
  • Xml WebService完全实例解析(一)
  • 团队开发 与 博客
  • VB打开数据库的问题
  • DirectFB代码导读
  • 【相关评论】
    没有相关评论
    【发表评论】
    姓名:
    邮件:
    随机码*
    评论*
          
    |  首 页  |  版权声明  |  联系我们   |  网站地图  |
    CopyRight © 2004-2007 软讯网络 All Rigths Reserved.