C语言内存分配详解5
};
void UseMallocFree(void)
{
Obj *a = (obj *)malloc(sizeof(obj)); // 申请动态内存
a->Initialize(); // 初始化
//…
a->Destroy(); // 清除工作
free(a); // 释放内存
}
void UseNewDelete(void)
{
Obj *a = new Obj; // 申请动态内存并且初始化
//…
delete a; // 清除并且释放内存
}
示例6 用malloc/free和new/delete如何实现对象的动态内存管理
类Obj的函数Initialize模拟了构造函数的功能,函数Destroy模拟了析构函数的功能。
函数UseMallocFree中,由于malloc/free不能执行构造函数与析构函数,必须调用成员函数
Initialize和Destroy来完成初始化与清除工作。函数UseNewDelete则简单得多。
所以我们不要企图用malloc/free来完成动态对象的内存管理,应该用new/delete。由于
内部数据类型的"对象"没有构造与析构的过程,对它们而言malloc/free和new/delete是等
价的。
既然new/delete的功能完全覆盖了malloc/free,为什么C 不把malloc/free淘汰出局呢?
这是因为C 程序经常要调用C函数,而C程序只能用malloc/free管理动态内存。
如果用free释放"new创建的动态对象",那么该对象因无法执行析构函数而可能导致程
序出错。如果用delete释放"malloc申请的动态内存",理论上讲程序不会出错,但是该程序
的可读性很差。所以new/delete必须配对使用,malloc/free也一样。
7、内存耗尽怎么办?
如果在申请动态内存时找不到足够大的内存块,malloc和new将返回NULL指针,宣告内存
申请失败。通常有三种方式处理"内存耗尽"问题。
(1)判断指针是否为NULL,如果是则马上用return语句终止本函数。例如:
void Func(void)
{
A *a = new A;
if(a == NULL)
{
return;
}
…
}
(2)判断指针是否为NULL,如果是则马上用exit(1)终止整个程序的运行。例如:
void Func(void)
{
A *a = new A;
if(a == NULL)
{
exit(1);
}
…
}
(3)为new和malloc设置异常处理函数。例如Visual C 可以用_set_new_hander函数为
new设置用户自己定义的异常处理函数,也可以让malloc享用与new相同的异常处理函数。详
细内容请参考C 使用手册。
上述(1)(2)方式使用最普遍。如果一个函数内有多处需要申请动态内存,那么方式(1)
就显得力不从心(释放内存很麻烦),应该用方式(2)来处理。
很多人不忍心用exit(1),问:"不编写出错处理程序,让操作系统自己解决行不行?"
不行。如果发生"内存耗尽"这样的事情,一般说来应用程序已经无药可救。如果不用
exit(1) 把坏程序杀死,它可能会害死操作系统。道理如同:如果不把歹徒击毙,歹徒在老死之
前会犯下更多的罪。
有一个很重要的现象要告诉大家。对于32位以上的应用程序而言,无论怎样使用malloc
与new,几乎不可能导致"内存耗尽"。我在windows 98下用Visual C 编写了测试程序,见示
例7。这个程序会无休止地运行下去,根本不会终止。因为32位操作系统支持"虚存",内存
用完了,自动用硬盘空间顶替。我只听到硬盘嘎吱嘎吱地响,Window 98已经累得对键盘、鼠标
毫无反应。
我可以得出这么一个结论:对于32位以上的应用程序,"内存耗尽"错误处理程序毫无用
处。这下可把Unix和windows程序员们乐坏了:反正错误处理程序不起作用,我就不写了,省
了很多麻烦。
我不想误导读者,必须强调:不加错误处理将导致程序的质量很差,千万不可因小失大。
void main(void)
{
float *p = NULL;
while(TRUE)
{
p = new float[1000000];
if(p==NULL)
exit(1);
}
}
示例7试图耗尽操作系统的内存
声明: 除非转自他站(如有侵权,请联系处理)外,本文采用 BY-NC-SA 协议进行授权 | 智乐兔
转载请注明:转自《C语言内存分配详解5》
本文地址:https://www.zhiletu.com/archives-649.html
关注公众号:
微信赞赏支付宝赞赏