我如何正确处理C中的malloc失败,尤其是当有多个malloc时? [英] How can I correctly handle malloc failure in C, especially when there is more than one malloc?
问题描述
假设这是我的代码的一部分:
int foo()
{
char *p, *q ;
if((p = malloc(BUFSIZ)) == NULL) {
return ERROR_CODE;
}
if((q = malloc(BUFSIZ)) == NULL) {
free(p)
return ERROR_CODE;
}
/* Do some other work... */
free(p);
free(q);
}
由于第一个malloc
可能成功但第二个malloc
失败,所以我在第二个错误处理程序"中使用free(p)
.但是,如果还有更多malloc
,又想修改代码(调整其顺序,添加或删除一些malloc
)怎么办?
我知道在C ++中有诸如RAII和异常安全之类的东西.但是,总的来说,处理C中malloc
失败的正确方法是什么? (也许使用某些goto
?)
您的代码很好,但是对于很多变量,我希望:
int
foo()
{
char *p = NULL;
char *q = NULL;
int ret = 0;
if (NULL == (p = malloc(BUFSIZ)))
{
ret = ERROR_CODE;
goto error;
}
// possibly do something here
if (NULL == (q = malloc(BUFSIZ)))
{
ret = ERROR_CODE;
goto error;
}
// insert similar repetitions
// hopefully do something here
error:
free (p);
free (q);
return ret;
}
请注意,释放NULL
被定义为无操作.
这避免了n
变量的n
缩进级别.您可以类似地清理文件句柄等(尽管您必须在close()
周围加上条件).
现在,如果您知道可以一次分配它们,那么 dasblinkenlight 有一个很好的答案,但这是另一种方法:
int
foo()
{
int ret = 0;
char *p = malloc(BUFSIZ);
char *q = malloc(BUFSIZ);
char *r = malloc(BUFSIZ);
if (!p || !q || !r)
{
ret = ERROR_CODE;
goto exit;
}
// do something
exit:
free(p);
free(q);
free(r);
return ret;
}
最后的可能性:如果您实际上想在malloc
失败时退出程序,请考虑使用mallopt
的M_CHECK_ACTION
选项.这样可以检查malloc()
故障,并调用abort()
,可能会显示一条有用的消息.
在手册页中:
NAME
mallopt
-设置内存分配参数简介
#include <malloc.h> int mallopt(int param, int value);
说明
mallopt()
函数可调整控制内存分配功能行为的参数(请参见malloc(3)
).param
参数指定要修改的参数,而value
指定该参数的新值.可以为
param
指定以下值:
M_CHECK_ACTION
设置此参数可控制在检测到各种编程错误(例如,释放同一指针两次)时glibc的响应方式.分配给该参数的值的3个最低有效位(2、1,和0)确定glibc行为,如下所示:
位0 :如果设置了此位,则在
stderr
上打印一条单行消息,其中提供有关错误的详细信息.消息以字符串"*** glibc detected ***"
开头,后跟程序名称,检测到错误的内存分配函数的名称,错误的简要说明以及检测到错误的内存地址.>位1 :如果设置了此位,则在打印由位0指定的任何错误消息后,将通过调用
abort(3)
终止程序.在从2.4开始的glibc版本中,如果还设置了位0,则在打印错误消息和中止之间,程序还将以backtrace(3)
的方式打印堆栈跟踪,并以(请参见 proc(5)
).位2 :(自glibc 2.4起)仅当还设置了位0时,此位才有效.如果设置了此位,则描述错误的单行消息将简化为仅包含检测到错误的函数的名称以及错误的简要说明.
Suppose this is a part of my code:
int foo()
{
char *p, *q ;
if((p = malloc(BUFSIZ)) == NULL) {
return ERROR_CODE;
}
if((q = malloc(BUFSIZ)) == NULL) {
free(p)
return ERROR_CODE;
}
/* Do some other work... */
free(p);
free(q);
}
Since it's possible that the first malloc
is successful but the second one fails, I use free(p)
in the second "error handler". But what if there are more malloc
's and what if I want to modify the code (adjusting their orders, adding or deleting some malloc
)?
I know in C++ there are things like RAII and exception safe, etc. But in general, what is the correct way to handle malloc
failure in C? (maybe using some goto
?)
Your code is fine, but for lots of variables, I'd prefer:
int
foo()
{
char *p = NULL;
char *q = NULL;
int ret = 0;
if (NULL == (p = malloc(BUFSIZ)))
{
ret = ERROR_CODE;
goto error;
}
// possibly do something here
if (NULL == (q = malloc(BUFSIZ)))
{
ret = ERROR_CODE;
goto error;
}
// insert similar repetitions
// hopefully do something here
error:
free (p);
free (q);
return ret;
}
Note that freeing NULL
is defined as a no-op.
This avoids n
levels of indent for n
variables. You can clean up filehandles etc. similarly (though you'll have to put a condition around the close()
).
Now, if you know you can allocate them all at once, then dasblinkenlight has a good answer, but here's another way:
int
foo()
{
int ret = 0;
char *p = malloc(BUFSIZ);
char *q = malloc(BUFSIZ);
char *r = malloc(BUFSIZ);
if (!p || !q || !r)
{
ret = ERROR_CODE;
goto exit;
}
// do something
exit:
free(p);
free(q);
free(r);
return ret;
}
Final possibility: if you actually want to exit the program on malloc
fail, consider using mallopt
's M_CHECK_ACTION
option. This makes malloc()
faults get checked, and calls abort()
, possibly printing a helpful message.
From the man page:
NAME
mallopt
- set memory allocation parametersSYNOPSIS
#include <malloc.h> int mallopt(int param, int value);
DESCRIPTION
The
mallopt()
function adjusts parameters that control the behavior of the memory-allocation functions (seemalloc(3)
). Theparam
argument specifies the parameter to be modified, andvalue
specifies the new value for that parameter.The following values can be specified for
param
:
M_CHECK_ACTION
Setting this parameter controls how glibc responds when various kinds of programming errors are detected (e.g., freeing the same pointer twice). The 3 least significant bits (2, 1, and 0) of the value assigned to this parameter determine the glibc behavior, as follows:
Bit 0: If this bit is set, then print a one-line message on
stderr
that provides details about the error. The message starts with the string"*** glibc detected ***"
, followed by the program name, the name of the memory-allocation function in which the error was detected, a brief description of the error, and the memory address where the error was detected.Bit 1: If this bit is set, then, after printing any error message specified by bit 0, the program is terminated by calling
abort(3)
. In glibc versions since 2.4, if bit 0 is also set, then, between printing the error message and aborting, the program also prints a stack trace in the manner ofbacktrace(3)
, and prints the process's memory mapping in the style of/proc/[pid]/maps
(seeproc(5)
).Bit 2: (since glibc 2.4) This bit has an effect only if bit 0 is also set. If this bit is set, then the one-line message describing the error is simplified to contain just the name of the function where the error was detected and the brief description of the error.
这篇关于我如何正确处理C中的malloc失败,尤其是当有多个malloc时?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!