2012年6月21日星期四

资源的拥有权


资源的拥有权
     -- C++程序申请与释放资源小结

开篇先引用一下,《Effective C++》的条款16:成对使用new和delete时要采取相同形式。简单的示例就是下面这样的,如下:

  example 1.
     type* ptr = new type;
     ...
     delete ptr;


  example 2.   
     type* ptr = new[10] type;
     ...
     delete[] ptr;

 
  还有C语言的版本,如下:
example 3.
     type* ptr = (type*) malloc(sizeof(type));
     ...
     free(ptr);   
      
一条编程实践的经验条款,经如上的简单示例显得很简单,浅显易懂。类似地,我想在此延伸到另一点:在哪里申请资源,最后就在哪里释放资源吧。
PS. 这里提到的“哪里”,其实理解了模块更好一些。若缩小了(作用域)范围如函数显然不妥,做不到在函数A申请资源,又在函数A释放资源,毕竟资源是要提供给对外使用的。若“哪里”理解成类型,好像还可以如某工厂类,其负责对象的创建和析构。

比如说,在模块A申请资源R,资源R属于多模块B,C,D等共享的,那么最后应该同样在模块A释放资源R。
虽然,一般情况下你在其它模块最后使用完资源R之后即完成释放,不会出现什么问题,但是这样的逻辑看着也令人觉得也不合理乎。“某女人生的孩子,日子过着过着,结果孩子长大成人了,却客死他乡了。”多么令人遗憾,心生不妥啊。(额,我承认举得例子太言重,恐怖了)

某些情况下,这种做法(在其它模块是否资源R)明显会出现程序异常情况,如释放资源导致程序崩溃。

什么情况下呢?
答:当其它模块如B,C,D模块编译链接时候所使用的运行时库与模块A的不同,如VC++编译器的不同运行时库包括如下:
多线程 (/MT)
多线程调试 (/MTd)
多线程 DLL (/MD)
单线程 (/ML)
单线程调试 (/MLd)



还有另一种情况,更可能导致程序异常,模块A与其他模块使用着不同的内存分配器

所以,你应该(或必须)做到在同一模块申请和释放内存资源。如模块A存在这样成对接口:
resource* allocate_resourse(...);
void release_resourse(resource* res);

这样,不管模块A,或其他模块B,C,D若需要新的resource,即通过模块A接口allocate_resourse申请;若最后用完了resource,即通过模块A接口release_resourse完成释放。逻辑也足够简单。


忌讳、痛恨那种在模块A申请资源,却在其他模块做释放资源的。很可能,最后你(程序)怎么死的都不知道。
好吧,最后总结一句,资源的拥有权始终保持唯一性。

(完)

2012-06-18/ Junkun Huang.



没有评论:

发表评论