I don't believe this is a duplicate because the function does return in the happy path. Using the attribute no-return
allows the compiler to optimise on the assumption that the function never returns, which is not the case here.
I have come C code that either returns a pointer or calls another function to exit out of the program. This is in an if
statement, so either it returns the result or exits. As the function returns a void *
, the compiler warns that it's possible the function won't return a value (which is of course true):
error: control reaches end of non-void function [-Werror=return-type]
I can get around this by just adding return *temp;
to the end of the function but I'd like to be clear in my intent by having something like the unused variable attribute:
__attribute__((__unused__))
That way I can leave -Wall
on and not have to add unnecessary or possibly confusing code.
I'd also be up for rewriting the code if there's a better way to express this intent.
The code looks something like:
void *get_memory() {
void *temp = malloc(100);
if (temp) {
// do some setup work
return temp;
} else {
exit_program_with_epic_fail();
}
// Compiler warns if the following line isn't present
return temp;
}
There are 2 ways to get rid of the warning:
exit_program_with_epic_fail()
function with the appropriate attribute, _Noreturn
in C11, but there is no portable way to do this to pre-C11 compilers. Many compilers support __attribute__((noreturn))
, notably gcc, clang and tinycc, but it is an compiler specific extension.Here is a modified version:
void *get_memory(void) {
void *temp = malloc(100);
if (!temp) {
exit_program_with_epic_fail();
}
// do some setup work
return temp;
}
This seems to be a pure design problem.
The warning/error "control reaches end of non-void function" isn't the problem, it is rather just an indicator telling you where the actual problem is.
You could/should simply rewrite the function as
void *get_memory (void)
{
void *temp = malloc(100);
if(temp != NULL)
{
// do stuff
}
return temp;
}
And leave error handling to the caller. Because it is not an allocation function's job to terminate the application - that's bad design.
Alternative version with detailed error handling:
typedef enum
{
OK,
ERR_OUTOFMEMORY,
...
} err_t;
err_t get_memory (void** mem)
{
*mem = malloc(100);
if(*mem == NULL)
{
return ERR_OUTOFMEMORY;
}
// do stuff
return OK;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With