在黑暗中举起探索的火炬的网志
在喧闹、混杂的生活中
你应该与你的心灵和平相处
尽管这世上有很多假冒和欺骗
有很多单调乏味的工作
和众多破灭的梦幻
它仍然是一个美好的世界
记住:你应该努力去追求幸福。
是的,记住:你应该努力去追求幸福。
每个早晨灿烂的太阳升起的时候,
每个人都应
-
2004-04-05
[转载] Solmyr和Zero的故事 —— 内存,最后一块 - [C/C++开发专辑]
版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明
Solmyr和Zero的故事 —— 内存,最后一块 Zero -------------------------------------------------------------------------------- “Shit!又死机了。我已经在这平台上工作了一个月了。可死机的次数比我在这个月里被女孩甩的次数还多。为什么?还不是这该死的平台,为什么掌上系统的内存就和愿意和我说话的女孩一样少?”Solmyr抱怨道。 “兄弟,怎么了。”Zero问。 “Zero是我们这组的主程序员,他懂得很多,人长的也帅,很讨女孩子的欢心。甚至连美工组的Lili(长得比孙燕姿还好看)也暗恋他。”。Solmyr一边想,一边说,“老大,你看,又死机了。为什么我每次用动态内存超过10次,就crash了呢?” “我知道你原来是Java程序员,也许到现在,你还念念不忘那GC (垃圾收集机制,我说还不如叫上帝也哭泣-God Cry),可你要知道,你现在是在用C++编程,重要的是效率。” “效率,我……”忽然,Solmyr觉得嘴角边似乎有液体流过。那是Solmyr的口水。每次提到效率,Solmyr总要流口水,就像看到漂亮MM,Solmyr要喷鼻血一样。 “C++中,关于动态内存的是new and delete。” “我知道,”Solmyr急于表现自己,想证明自己对C++并不是一无所知,“我正在读Scott Meyer的More Effective C++。在C++中,new operator是C++内建的行为。任何人(也许除了Bjarne Stroustrup)都无法改变。new operator先调用一个名为operator new的函数动态申请内存。标准模式就像这样: void* operator new(size_t size); 然后在传回的void*指针上进行构造的行为。而delete operator则先析构对象,然后调用名为operator delete的函数,标准形式就像这样: void operator delete(void* pToDeAlloc) // GotW中说即使在指针参数后加上size_t size,仍然是标准形式。 // size_t size的作用是检查所要卸除的内存是否是期望的大小, //如果在类层次中定义的话,只要基类是virtual destructor,那么size可以 // 确保是正确大小。 而placement new……。” “唔,说得不错,有进步。关于placement new/delete,先知Meyer[1]有详细的论述。原来的placement new仅仅是这样: void* operator new(size_t, void* pMem) { return pMem; } ‘ 随着时间过去,任何‘要求额外引数’的 operator new 版本,也都渐渐采用 placement new 这个术语。事实上这个术语已经被铭记於 C++ 标准规格中。因此,当 C++ 程序员谈到所谓的 placement new 函数,他们所谈的可能是上述那个‘需要额外一个 void* 参数,用以指出物件置于何处’的版本,但也可能是指那些‘所需参数比单一而必要之 size_t 引数更多’的任何 operator new 版本,包括上述函数,也包括其他‘参数更多’的 operator new 函数。’——引自[1]。 现在我们来考虑一个问题,如果在operator new结束申请内存后,构造函数抛出了异常,那么已经申请的内存谁来回收,答案当然是编译器。因为整个new operator还未结束。所以你无法获得控制权。如果你对operator new/delete进行了重载,那么编译器会调用那个operator delete呢?由于不同的operator new可能通过不同的方法获得内存,而让不知道怎样分配的operator delete去释放内存显然是不负责任的。所以编译器假定哪个operator delete与operator new有相同的参数(除了size_t size和void* pDeAlloc),那么那个operator delete便知道operator new怎样获得内存。构造函数抛出异常后,也会调用与operator new相同参数的operator delete来释放内存。” “那么,我该怎么解决现在的问题呢?” “别那么急,已经下午五点了。该回家了,别让人以为程序员是夜游神。回家看看Effective C++第二部分和GotW9, GotW10。明天再说吧。” 第二天一早,Solmyr啃着大饼走进了办公室,看到Guru Zero早已姿势优雅地坐在电脑前收发Email,不禁自惭形秽,连忙放下手中的大饼,跑去和Zero说:“老大,昨天晚上,我挑灯夜读,总结出两点: 1. 如果你写了一个operator new,请对应写一个operator delete。 2. 不要delete不是自己new来的内存。 “嗯,不错,怎么我看上去,就象是Effective C++中的条款呢?你有没有自己想过关于placement delete的问题?” “placement delete有什么问题吗?”Solmyr一脸茫然的问道。 “你有没有试过把一块用placement new申请得到的内存用placement delete卸除掉呢?不妨你现在试试看。” 只见Solmyr跑到一台电脑前,两手如飞在键盘上敲击,可是我们能听到的只有他的唉声叹气和编译器的哇哇大叫。Solmyr实在是没办法,只能向Zero求教。Zero喝了一口咖啡,说道:“我们平时写的那些要求额外参数的operator delete只有在构造函数抛出异常时,才会被编译器自动调用,而我们是不可能手工调用到任何带有额外参数的delete的,为什么没有一个内建的‘placement delete’来与‘placement new’相匹配的原因在于没有办法保证它被正确使用,在C++类型系统中,无法推断一个指针从哪里获得它指向的内存,可能是指向heap,也可
http://junglesong.yourblog.org/logs/137072.html
随机文章:
[轉貼] TurboC 2.0 函数中文说明大全(4) 作者:胡颖卓 2004-06-28[轉貼] TurboC 2.0 函数中文说明大全(2) 作者:胡颖卓 2004-06-28[转载] Solmyr 的小品文系列之八:拷贝 2004-04-05[转载] Solmyr 的小品文系列之六:成对出现 2004-04-05ZT:欣赏优美的代码(4) 作者:axing 2004-02-07
收藏到:Del.icio.us





