堆内存与栈内存小议(转载)

 在标准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上模拟他们进程和内存管理。最简单的实现在函数种分配数组进行各种访问,并观察堆栈

http://blog.21ic.com/user1/3664/archives/2008/46793.html 转载   作者 yuyixuantai 日期 2008-3-28 0:33:00

 

注:return语句不可返回指向“栈内存”的“指针”或者“引用”,因为该内存在函数体结束时被自动销毁。

        使用free或delete释放了内存后,没有将指针设置为NULL。导致产生“野指针”。

        数组要么在静态存储区被创建(如全局数组),要么在栈上被创建。数组名对应着(而不是指向)一块内存,其地址与容量在生命期内保持不变,

只有数组的内容可以改变。

       指针可以随时指向任意类型的内存块,它的特征是“可变”,所以我们常用指针来操作动态内存。指针远比数组灵活,但也更危险。

指针p指向常量字符串“world”(位于静态存储区,内容为world\0),常量字符串的内容是不可以被修改的。从语法上看,编译器并不觉得语句p[0]= ‘X’有什么不妥,但是该语句企图修改常量字符串的内容而导致运行错误。

char a[] = “hello”;

a[0] = ‘X’;

cout << a << endl;

char *p = “world”;     // 注意p指向常量字符串

p[0] = ‘X’;             // 编译器不能发现该错误

cout << p << endl;

        示例7-3-1 修改数组和指针的内容

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值