zoukankan      html  css  js  c++  java
  • 我也要学C语言第二十三章:微软未公开的堆内存

    int main(int argc, char *argv[], char *envp[])
    {
    int a =1;
    int b =2;

    return0;
    }

    在这个代码中,变量a和b还有3个参数都在栈中,那么在栈里面分配的空间有什么特点的呢?!它们在编译器编译期限就为它们预留了空间。那么还有一个堆空间,它和栈空间有什么区别呢?!其实堆空间是在程序运行过程中,你需要什么就找它要什么。打个比方,就好像你去逛超市,你去之前你想买什么,你在脑子里面都已经想好了,到了超市你直接把你需要东西都买啦!这时候你买的这些东西一般都在栈中。但是你在超市里或者看到你当时还没有想买的又很想吃的东西呢,你肯定就再买啦!但是这些东西都是你出门前没有想到的东西,这时候你就需要另外规划钱了,你就再多计划点钱了,但是你身没带那么多钱怎么呀!你就去借点,在计算机中就是找操作系统去借啦!然后去买啦!这时候,这些东西一般就在堆中。而且在计算机里,你就需要向操作系统说,我还要点东西,呵呵!但是找操作系统再要内存,不一定要得到啊,有时候万一没有了呢,所以要内存的时候就需要做1个检查。因为是找操作系统借的,所以当用完了后还需要还给操作系统!如果不还就不行啊,因为你不还,大家也都不还,这样内存就耗尽了,就会出问题了。到底我们如何简单分辨到底在堆中还是栈中呢?!只要我们把握好申请内存的时机,计划内的就在栈,计划外的就在堆。另外要注意一个问题,堆栈是指的栈,和堆没关系。这就好比韩信好佩刀剑,其实他就是佩的剑。

    C语言库中操作堆的2个函数malloc和free 

    malloc这个函数就是找操作系统申请内存,这个函数是这样定义的:

    void *malloc(size_t size);    Required Header[<stdlib.h> and <malloc.h>] 

    首先,这个函数是个C标准的库函数,当你使用malloc的时候,你不需要关系找操作系统申请内存的具体流程。否则你要用一个当地平台的API去申请内存。malloc.h相当于1个中介所呢!

    如何使用malloc

      首先你要包含库,stdlib.h或者malloc.h. 你在调用此函数的时候,你需要提供size_t类型的size. size_t其实就是int.然后返回值是一个void *. void *是一个指针,设计malloc的人无法知道你是把这段内存干嘛用呢?!所以只能返回void *啦!所以你用的时候就要进行一次强制转换,转换成你所设计的使用。

    malloc是借,free是还

      嘿嘿!你向操作系统借了东西,是要还的啊!操作系统就相当于上帝,你欠上帝的始终都要还的,呵呵!

    free的定义:void free(void *memblock);

    当你还内存的时候,你就需要告诉它你要还什么,这个*memblock参数就是申请到的内存首地址。

    程序实例:

    int main()
    {
    int*pInt = NULL;//必须先初始化为NULL,
    pInt = (int*)malloc(sizeof(int));//一定要转换哦!不然报错!强制为你所 设计的

    if(NULL == pInt)//必须做检查,检查申请成功了没,如果申请成功返回首地址,不成功就返回NULL也就是0。
    {
    return-1;//这里设置成你的合适的处理方式,不一定是退出。
    }

    if(pInt)//在释放之前必须做检查。
    {
    free(pInt);
    pInt
    = NULL;//释放完了以后必须再次设置为NULL,杜绝野指针。
    }

    return0;
    }

    我们来看看,我们的堆空间到底是什么样子的。

    这里看到了1个以前没有看到过的地址段,0x003706e0。这个应该就是操作系统分配的堆空间的地址,这个地址我们从内存中可以看到1些特点.在调试版下,它有一些结构去辅助程序的调试。我们看到这里地址值被初始化为CD,在栈空间是初始化的CC。哦!原来是这样,那么我们以后只要看到CD了,就知道是调试版的啦!然后再单步一下,值就赋为7了。

    内存泄漏

    (上面截图有个书写错误,就是sizeof(char)应该是sizeof(char[]))这个程序正确的吗?我们仔细一瞧,不对呀!0x0042028是只读数据区的地址呀!这样的话,就是说,Ipstr的值被覆盖了,这样的话,原来的内存就无法释放了,这样的话就叫内存泄漏了。这样的话free的时候就要出错啦!为什么会出错啊,就是因为释放了1个常量。

    以后千万不要犯这样的错误啊!那么要怎么写才对呢?!我们这里就要用到1个函数啦!:strcpy(lpstr, "Hello world");

    但是还是有个问题,就是这里只是1个记录,要是我要把1千万个学生放如内存,如何去释放呢,我相信继续学习后某天一定会知道的了。

    刚才程序报错,为什么它知道我们释放的不是堆内存呢?!进一步调试下,

    因为堆内存都微软没有公开的资料,所以很多堆的特性都是通过逆向工程,和通过前辈高人的研究成果。堆很有特点:

    1:首先调试版下,初始化为全CD

    2:前后4个FD,防止溢出,如果FD被破坏,调试版的时候会给警告

    3:堆是一个双项链表结构,在当前堆指针减16的地方就到了堆的数据长度,这就是为什么后面FD位置的确定

    4:这个是和操作系统版本相关的,以上适合于WINDOWS XP

    5:如果FD被破坏了,你可以手工修复,程序一样可以正确运行

  • 相关阅读:
    Netty 心跳处理
    Netty 搭建 WebSocket 服务端
    Spring Boot 集成 MQTT
    Spring Boot 上传文件
    在 CentOS 7 安装 Tomcat
    神坑之 6666 端口 (默认非安全端口)
    MongoTemplate 移除 _class 字段
    在 CentOS 7 安装 RabbitMQ
    MongoDB 分片集群配置
    tensorflow学习(一)
  • 原文地址:https://www.cnblogs.com/dodolook/p/2096738.html
Copyright © 2011-2022 走看看