Chinaunix首页 | 论坛 | 博客
  • 博客访问: 27841
  • 博文数量: 4
  • 博客积分: 107
  • 博客等级: 民兵
  • 技术积分: 40
  • 用 户 组: 普通用户
  • 注册时间: 2012-03-15 16:39
文章分类

全部博文(4)

文章存档

2012年(4)

分类: C/C++

2012-06-10 11:08:50

 在标准C语言上,使用malloc等内存分配函数获取内存既是从堆中分配内存,而在一个函数体中例如定义一个数组之类的操作是从栈中分配内存。

    从堆中分配的内存需要程序员手动释放,如果不释放,而系统内存管理器又不自动回收这些堆内存的话(实现这一项功能的系统很少),那就一直被占用。而栈内存在函数体内一直存在,你无法丢掉,在离开函数体后,立即被销毁,你无法挽留。

    如果老是申请堆内存,而不释放,内存会越来越少,很明显的结果是系统变慢或者申请不到新的堆内存。而过度的申请栈内存(可以试试在函数中申请一个1G的数组!),会导致栈被压爆,结果是灾难性的。栈都爆了,谁知道函数会跑到哪里去?!

    我们掌握堆内存的权柄就是返回的指针,一旦丢掉了指针,便无法在我们视野内释放它。这便是内存泄露。而如果在函数中申请一个数组,在函数体外调用使用这块栈内存,结果谁也无法预测。
   
    申请栈内存的时间是基本确定的。核心只要栈指针的偏移和对它进行初始化(如果必要的话)。但堆中的时间是无法预测的,这是内存管理器的任务,跟他的算法和当前的堆内存结构有关,也许很快,也许很慢。两者在这里不存在可比性,尽管大多数情况下栈内存的申请的确比堆内存要快。
    申请的时候,栈内存几乎等同与申请大小,大多数的偏差是内存对齐引发的几个字节影响。但对内存但实际也会会相差很大(这主要源于内存管理器算法)。常见的内存管理都是按照基本内存块大小来分配的。在一个基本单元是1024Byte的管理器上,哪怕你只申请一个Byte,它也会给你1024个。频繁的申请小的堆内存是不明智的。
    在申请和销毁之外的使用过程中,他们是一样,可以同样对待。一般情况下,他们具有同样的访问速度,都不要进行越界访问,哪怕堆内存先后越界暂时不会出错。

    栈内存和堆内存的大小也没有可比性。栈内存大小跟IC,编译器,OS相关。而对堆内存的大小一般是内存管理器说了算。X86上Windos下VC编译的代码只是N种情况之一。并不具备多少代表性。至于磁盘是否能为堆内存撑腰,完全在于你使用的内存管理器和IC是否支持虚拟内存。

    从更底层一点来说,堆和栈只是对他的可见内存(可能是物理内存)的使用方式。如果我们你有1G的内存,我们可以给分256K给栈,然后拿500M给内存管理器。于是前者成了栈内存,后者成了堆内存。当然,如果你要给栈800M,对256个字节也没问题。如果我有块干净的IC和系统,所有的东西都自己起步,就可以这样干。只需要拿一块单片机系统或者直接在VC上模拟也可以。

     malloc只是标准C种实现动态内存申请的一种方式而已。它和堆内存申请并不等价。在我们自己内存管理器种,完全可以是任何名称(不考虑编程规范和接口标准的话)。


     参考与实现:
     参阅任何一本数据结构和操作系统书籍。
     参阅任何一种小的OS(uC_OS II就可以了);
     自己在单片机或者VC上模拟他们进程和内存管理。最简单的实现在函数种分配数组进行各种访问,并观察堆栈

。定一个很大数组,进行分配和回收。

阅读(1774) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~