问题
Can I put malloc in do...while block to ensure successful allocation?
like:
#define STR_SIZE 1024 * 1024
char *str;
do
str = (char *) malloc(STR_SIZE);
while ( !str );
回答1:
It probably won't work, because malloc
rarely fails, it fails when resources are exhausted, and these won't be available soon.
the only common case when malloc
could get more resources is if some other big process releases a lot of memory, and that seldom happens and may never happens; if you cared about that add at least a sleep
in your loop, and be prepared to handle the case when malloc
genuinely fails and always return NULL
.
The better practice is to test malloc
result and exit with failure and error message, e.g.
char* str = malloc(STR_SIZE);
if (!str) {
perror("malloc failed for str");
exit (EXIT_FAILURE);
}
And every program should deal with the case when malloc
fails (usually by exiting with an error message).
A lot of programs call xmalloc
a function which exit
-s or abort
-s when malloc
fails, and return the allocated zone when it succeeds
Dealing sensibly with a malloc failure (that is doing something to be able to continue execution) is really hard. Some programs might for instance free
some other global data. Actually this amounts to implement some specialized garbage collection mechanism. Some servers might just fail the current request (and should do that with great care, releasing all the resources used by that current failed request).
And malloc
can genuinely fail, when you are requiring more resources that those available. So you have to handle that case.
BTW, you could consider using Boehm's conservative garbage collector and use GC_malloc
instead of malloc
and not caring about its failure and about free
-ing. (I think that Boehm's GC would abort the program when not enough memory).
回答2:
As other answers point out, your code is flawed. The idea behind, however, is not entirely unreasonable.
The classic approach for handling malloc
failure is for the program to exit, as outlined in Basile's answer. Code that checks the return value of malloc
is often placed in a generic wrapper function called xmalloc
or such, and used consistently in place of malloc
. This is easy to implement and reason about, but it is not without flaws. It makes a lot of sense for short-lived command-line programs such as those typically invoked from a Unix shell, but it fails for interactive programs where it is inappropriate for a program to immediately drop dead, even if it does run out of memory. It is also unsuitable for library code, as the program that uses the library might not want the process to exit merely because a single allocation failed.
Retrying the allocation makes sense when there is a good chance that the memory problem did not result from the activity of your program. For example, a multi-process HTTP server might not want to refuse a request and end the process as soon as a single memory allocation fails. However, a good implementation would: 1) take care to sleep between the requests to avoid busy-looping and give the system a chance to recover, and 2) ensure that the process exits after a number of iterations, in case it is the process itself that is causing the allocation failure. For example:
void *safe_malloc(size_t howmuch)
{
int i = 0;
while (i++ < 10) {
void *ptr = malloc(howmuch);
if (ptr)
return ptr;
sleep(i);
}
perror("malloc");
exit(EXIT_FAILURE);
}
This approach has been used in servers such as the now-obsolete phttpd web server.
A different approach to malloc
failure in interactive applications is the one used by Emacs: a fixed amount of memory is allocated at startup and saved for later. When a memory allocation fails, the relief memory is freed and a Lisp-level exception is raised, abandoning the current operation. A warning message is displayed up to the user explaining the situation. The freed memory enables the program to continue working for long enough for the user to save their work before Emacs goes down.
回答3:
Certainly, but if STR_SIZE
is unreasonable this will lock your code forever.
Malloc can also fail on, rare occasions, if your memory is very fragmented. In this case your code will work.
回答4:
you could, although it's a rarity malloc will fail, syntactically correct but i don't if it's logically correct, ill try to code if it works.
来源:https://stackoverflow.com/questions/14180577/malloc-in-do-while-block