【发布时间】:2019-01-08 11:14:44
【问题描述】:
我正在为一个 uni 项目用 C 语言编写一个多线程服务器,我很难弄清楚如何以一种好的、可读的和标准的方式进行错误处理。
现在,如果程序成功终止,我会在程序结束时释放所有分配的内存。但是如果执行过程中出现致命错误(例如 malloc 返回NULL)怎么办?
例如,假设我有一个自定义数据类型mydata_t 和一个构造函数mydata_t *mydata_init(),我的程序的多个模块都在使用它。在网上看到一些代码后,我是这样写的:
mydata_t *mydata_init() {
mydata_t *mydata = malloc(sizeof(mydata_t));
if (!mydata) return NULL;
mydata->field1 = malloc(sizeof(mydata2_t));
if (!mydata->field1) return NULL;
mydata->field2 = malloc(sizeof(mydata3_t));
if (!mydata->field2) return NULL;
/*
Initialization of other fields
*/
return mydata;
}
看起来确实很干净,但这是“标准”的做法吗?
特别是,如果其中一个 malloc 返回NULL 怎么办?是否有必要释放所有先前分配的内存?把代码改成这样合理吗?
mydata_t *mydata_init() {
mydata_t *mydata = malloc(sizeof(mydata_t));
if (!mydata) goto err_1;
mydata->field1 = malloc(sizeof(mydata2_t));
if (!mydata->field1) goto err_2;
mydata->field2 = malloc(sizeof(mydata3_t));
if (!mydata->field2) goto err_3;
/*
Initialization of other fields
*/
return mydata;
/*
Other tags
*/
err_3:
free(mydata->field1);
err_2:
free(mydata);
err_1:
return NULL;
}
【问题讨论】:
-
难道你不能在尝试释放每个指针之前检查它是否不为 NULL 吗?
-
你也可以试试codereview.stackexchange.com。
-
'我会在最后释放所有分配的内存' 除非你的操作系统有问题,否则不要浪费你的时间和精力。一个很好的理由是,与终止进程时的操作系统不同,您不能总是保证其他线程没有使用您认为需要释放的内存。另一个是你问这个问题的原因 - 致命错误可能已经破坏了支持 malloc/calloc/free 的 C 子分配器。如果您在非平凡的操作系统上运行,例如。 Windows/linux,别再为多余的内存释放而烦恼了,滚吧。
-
@MartinJames:这或多或少是我的想法。该错误是一个致命错误,那么如果应用程序崩溃,我为什么要管理内存呢?感觉这只会使系统的恢复变得更糟,更不用说代码的可读性了。如果程序运行在一个非平凡的操作系统上,所有这一切,就像你说的那样。
标签: c memory-management error-handling goto