在 ICC 中如何正常的进行动态内存分配

    在 ICC 中,我们是无法直接使用 C 语言基本库函数 malloc()和 free()进
行动态内存分配和释放——即便包含了 C 语言标准库“ stdlib.h”也是一样。
这是因为, 这里的动态内存分配是一种堆式分配。 为了节省空间开支, ICC
没有为我们开辟默认的堆空间用于动态内存分配。使用这一功能,我们需

要人工添加一个(或多个)堆。

    在 ICC 提供的 C 语言标准库函数 stdlib.h 中,有一个非标准的函数
_NewHeap,它的原形为:
void _NewHeap(void *start, void *end);
通过该函数, 我们只需要提供堆的起始地址和终止地址就可以将堆添加到

系统中,所有动态分配的内存,都将从这一空间划分出去。例如:
extern char _bss_end;
_NewHeap(&_bss_end+1, &_bss_end + 201); //添加 200 字节的堆空间


上面的代码中,我们添加了一个大小为 200 字节的堆。如果这是第一
次向系统中添加堆空间,那么从此以后,我们便能正常地使用 malloc 函数
动态的获取我们需要的存储空间了。需要补充说明的是,函数 _NewHeap
可以被多次使用,向系统中添加若干个堆,而这些堆并不要求是相互连续
的。例如在上述代码的基础上,我们还可以追加一段数组空间作为堆,加
入到系统中:
unsigned char OurArray[100] = {0};
_NewHeap(OurArray,OurArray+100); //将数组作为堆,进行添加

这里,我们需要补充强调一下:调用函数_NewHeap()时必须传递两个
参数:一个是堆的起始地址,一个是堆的终止地址。如果我们试图将某种
类型的数组作为堆添加到系统中,那么第一个参数使用数组名(所代表的
地址)是没有任何问题的。关键在于,函数要求我们同时给出数组的终止
地址, 这时我们就必须进行地址计算——由数组名代表的起始地址加上数
组元素的个数来获取数组的终止地址,注意,这里加上的不是数组的实际
字节数,而是数组元素的个数。根据本章前面指针介绍过的指针加减知识
容易理解,数组名所代表的地址是有类型区别的,对该地址进行加减计算
时,每加减 n 的数字量,其计算出的地址结果都相当于该地址加减了 n *
sizeof
(数组类型)个字节。此时,如果我们自作聪明的在数组名称代表的地
址上增加数组的实际字节数作为偏移量,那么最终得到的结果,可能已近
相差了十万八千里——对这一错误毫不知情的系统, 在进行动态内存分配
时,有发生内存入侵的可能。例如:

unsigned int OurArray[100] = {0};
_NewHeap(OurArray,OurArray+100); //实际添加了 200 个字节
通过_NewHeap, 我们将指定了起始和终止地址的一段连续空间添加到
系统中用于动态内存的分配。为了提高空间的利用率,对于已经不再使用
的空间,我们应该及时通过 free()函数进行释放。对 free 函数来说,他需
要我们提供一个有效的地址——该地址属于一个已经被分配出去的动态
内存。对相当一部分的 C 语言来说,向 free 函数传递一个已经被释放过了
的空间地址, 或者一个根本就不属于堆空间的地址并不一定会对程序的运
行有任何的影响,但是ICC 目前版本(截止到 ICC7.13A)的 free 函数来
说,这种“欺骗”是不被允许的。如果你为了保险在程序中不小心对于同
一个空间释放了两次,那么最后一次调用 free 将导致死循环。如果你的程
序中恰巧开启了看门狗,后果不言自明。













评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值