iphone 如何渡过内存危机(OOM)
来源:互联网 发布:windows安装git服务器 编辑:程序博客网 时间:2024/04/27 23:23
讲两件事情:第一件是我们必须做到的,不然OOM来袭会造成程序崩溃,第二件是我们最好做到的,不然OOM来袭我们不能彻底恢复。
1。防止OOM恢复过程中的crash
假设一个类有如下初始化和清除代码:
如果new CMyOtherClass的过程中,内存耗尽,这个时候系统会直接跳转到异常处理代码,一般来说异常处理代码会清除掉当前所有context,重新来过。这个时候会调用Destroy()。这个时候m_pPointer是没有被赋值的。如果你没有正确的初始化的话,delete m_pPointer就会造成问题。
因此,正确的做法应该是这样:
当然,初始化也可以在constructor里面做。
这个故事告诉我们,在desktop里面看起来铁定会被执行的东西,在嵌入世界里可能会跑得没影。你要考虑到一个new,一个alloc,一个调用了这些东西的函数等,都有可能回不来。因此,在你准备随时“就义”之前,请安排好“后事”。
其实每个变量要初始化,这是常识。但是有的时候,看起来没问题的偷懒,就有可能引起严重问题。
2。防止内存孤儿的产生
另外一种情况,不是“秒杀”你的应用,而是会慢慢的让你的应用瘫痪掉,这就是内存泄漏。内存泄漏的一个原因是你忘了在合适的时候去清除你申请的内存了,这怪你自己太粗心。不过有的时候,可能由于你意想不到的原因,会导致“内存孤儿”的产生,也就是没人管、管不到的内存,从而造成内存泄漏。
举一个例子:
请注意我们已经吸取了上面讲的问题的教训,正确的初始化了,也能正确的清除。但是,以下的代码:
CMyClass* p = new CMyClass;
...
如果new CMyClass成功,但是在构建CMyClass的时候,new CMyOtherClass失败,会怎样呢?新创建的CMyClass对象里面的m_pPointer会保持为NULL,这个没问题,但是,CMyClass对象的指针,放到哪里去了呢?
答案是哪里也没有放,因为还没来得及赋值给p,程序执行就走了,离开了,不回来了。你制造了一个孤儿。这片内存(里面放着一个构建失败的CMyClass),永远没有机会被释放了,除非整个内存管理器被清除。
要怎么解决呢?方法就是两步构建。第一步,构建对象本身,第二步,构建对象内容。
改成这个样子:
调用的时候:
CMyClass* p = new CMyClass;
p->Init();
...
这样,无论Init()是否成功,p里面都放了CMyClass的指针。
其实我举的例子还是有问题的:如果p->Init()不成功,那么程序走了,临时变量p也会不见掉。正确的做法应该是将指针放到一个外部可以随时存取的context的成员中:
pContext->m_pPointer = new CMyClass;
pContext->m_pPointer->Init();
...
以上讲的两件事情,都不是什么大事,但是细节不注意,会给你们的代码带来大问题。请大家注意养成良好的设计和编码习惯,稍微注意一下,我们一定能渡过内存危机!
附: 上面的这两种思想在iphone sdk中有了很好的体现, 特别是第二件事,
Object *obj = [[Object alloc] init]; //这个其实这个就是一个两步构件的思想。
在iphone开发过程中使用了C++代码的兄弟们就更应该注意这个安全隐患。
1。防止OOM恢复过程中的crash
假设一个类有如下初始化和清除代码:
void CMyClass::Init(){ m_pPointer = new CMyOtherClass;}void CMyClass::Destroy(){ delete m_pPointer;}
如果new CMyOtherClass的过程中,内存耗尽,这个时候系统会直接跳转到异常处理代码,一般来说异常处理代码会清除掉当前所有context,重新来过。这个时候会调用Destroy()。这个时候m_pPointer是没有被赋值的。如果你没有正确的初始化的话,delete m_pPointer就会造成问题。
因此,正确的做法应该是这样:
void CMyClass::Init(){ m_pPointer = NULL; m_pPointer = new CMyOtherClass;}void CMyClass::Destroy(){ if (m_pPointer) delete m_pPointer;}
当然,初始化也可以在constructor里面做。
这个故事告诉我们,在desktop里面看起来铁定会被执行的东西,在嵌入世界里可能会跑得没影。你要考虑到一个new,一个alloc,一个调用了这些东西的函数等,都有可能回不来。因此,在你准备随时“就义”之前,请安排好“后事”。
其实每个变量要初始化,这是常识。但是有的时候,看起来没问题的偷懒,就有可能引起严重问题。
2。防止内存孤儿的产生
另外一种情况,不是“秒杀”你的应用,而是会慢慢的让你的应用瘫痪掉,这就是内存泄漏。内存泄漏的一个原因是你忘了在合适的时候去清除你申请的内存了,这怪你自己太粗心。不过有的时候,可能由于你意想不到的原因,会导致“内存孤儿”的产生,也就是没人管、管不到的内存,从而造成内存泄漏。
举一个例子:
CMyClass::CMyClass(){ m_pPointer = NULL; m_pPointer = new CMyOtherClass;}CMyClass::~CMyClass(){ if (m_pPointer) delete m_pPointer;}
请注意我们已经吸取了上面讲的问题的教训,正确的初始化了,也能正确的清除。但是,以下的代码:
CMyClass* p = new CMyClass;
...
如果new CMyClass成功,但是在构建CMyClass的时候,new CMyOtherClass失败,会怎样呢?新创建的CMyClass对象里面的m_pPointer会保持为NULL,这个没问题,但是,CMyClass对象的指针,放到哪里去了呢?
答案是哪里也没有放,因为还没来得及赋值给p,程序执行就走了,离开了,不回来了。你制造了一个孤儿。这片内存(里面放着一个构建失败的CMyClass),永远没有机会被释放了,除非整个内存管理器被清除。
要怎么解决呢?方法就是两步构建。第一步,构建对象本身,第二步,构建对象内容。
改成这个样子:
CMyClass::CMyClass(){ m_pPointer = NULL;}void CMyClass::Init(){ m_pPointer = new CMyOtherClass;}
调用的时候:
CMyClass* p = new CMyClass;
p->Init();
...
这样,无论Init()是否成功,p里面都放了CMyClass的指针。
其实我举的例子还是有问题的:如果p->Init()不成功,那么程序走了,临时变量p也会不见掉。正确的做法应该是将指针放到一个外部可以随时存取的context的成员中:
pContext->m_pPointer = new CMyClass;
pContext->m_pPointer->Init();
...
以上讲的两件事情,都不是什么大事,但是细节不注意,会给你们的代码带来大问题。请大家注意养成良好的设计和编码习惯,稍微注意一下,我们一定能渡过内存危机!
附: 上面的这两种思想在iphone sdk中有了很好的体现, 特别是第二件事,
Object *obj = [[Object alloc] init]; //这个其实这个就是一个两步构件的思想。
在iphone开发过程中使用了C++代码的兄弟们就更应该注意这个安全隐患。
- iphone 如何渡过内存危机(OOM)
- Android如何避免内存泄露及内存溢出(OOM)
- 大学是什么?如何渡过?
- 快速玩转大数据_顺利渡过34岁裁退危机
- 玩转大数据_顺利渡过34岁裁退危机
- 玩转大数据_顺利渡过34岁裁退危机!
- 为什么有些程序员悄无声息渡过35岁中年危机?
- 为什么有些程序员悄无声息渡过35岁中年危机?
- 如何渡过入职头30天
- Android 内存优化,如何避免OOM
- OOM(内存溢出)解决方案
- OOM内存溢出(转)
- 内存泄漏导致内存溢出(OOM)
- 内存溢出(OOM)与内存泄露
- 如何有效渡过充满迷茫的大学生活
- 如何有效渡过充满迷茫的大学生活
- 程序员如何渡过“五.一”短假?
- 产品经理如何渡过适应期
- 数据模型封装--行固定,列不固定(java)
- 国土面积计算
- jQuery1.6.2源码阅读笔记 【一】
- 程序员须注意的非技术性错误
- 图像编辑之对比度调整(亮度对比度的算法公式)
- iphone 如何渡过内存危机(OOM)
- select option 下拉框文本显示不全 处理办法.
- 控制图片比例、等比例控制图片最大宽高。
- 修改linux时间
- attr_accessor vs attr_accessible
- ibatis 例子(二)
- 新学期啦
- 我的好邻居,乔布斯
- ifconfig用法