设为首页 加入收藏

TOP

重构C资源释放代码
2014-11-23 22:08:19 来源: 作者: 【 】 浏览:0
Tags:重构 资源 释放 代码

今天我在维护一个C项目的时候发现有的函数内部有很多的return语句,每个return前面都有一段相同的资源释放的代码。代码看起来就像这样:

int f() {
char *p1 = (char*)malloc(1024 * sizeof(char));


int *p2 = (int*)malloc(10 * sizeof(int));


...

if (...) {

free(p1);


free(p2);


return 1;


}

for (...) {


if (...) {

free(p1);


free(p2);


return 2;

}


}


...


free(p1);

free(p2);


return 0;


}

上面的代码资源释放部分重复度太高,读起来不够清爽。更重要的是如果某一个return之前忘记了释放资源就会发生内存泄露,只能靠程序的作者和维护者随时提高警惕。这类问题在C++中可以通过RAII来很好地解决,但可惜C语言没有自动析构机制,所以,我们需要通过一些技巧来达到类似的效果。看下面的代码:

int void f() {

int return_code = 0;


char *p1 = (char*)malloc(1024 * sizeof(char));


int *p2 = (int*)malloc(10 * sizeof(int));


...

if (...) {

return_code = 1;


goto _END_F;

}

for (...) {


if (...) {

return_code = 2;
goto _END_F;


}

}


...


_END_F:


free(p1);

free(p2);


return return_code;


}

我们把资源释放代码统一放在函数末尾,并打上_END_F标签,把原来return的地方用goto _END_F替换。我们通过这种方式消除了资源释放部分的冗余代码,也一定程度上减小了忘记释放资源的风险。不过,由于现在需要每次在goto前面加上return_code=x,还是有一定的冗余和遗忘的危险。于是,我们可以通过下面的宏可以进一步完善:

#define RETURN(label, returnCode) { return_code = returnCode; goto label;}


这样我们就可以用RETURN(_END_F, 2)来一并实现设置返回值和goto的效果了,即简化了代码,又防止忘记设置返回值。 最终重构效果如下:


#define RETURN(label, returnCode) { return_code = returnCode; goto label;}

int void f() {

int return_code = 0;


char *p1 = (char*)malloc(1024 * sizeof(char));


int *p2 = (int*)malloc(10 * sizeof(int));


...

if (...) {

RETURN(_END_F, 1);


}

for (...) {


if (...) {


RETURN(_END_F, 2);

}

}


...


_END_F:


free(p1);

free(p2);


return return_code;


}

】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇用位操作实现的n皇后问题 下一篇问题一百四十五:发工资咯:)

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: