Let’s say I have a function to perform a small and particular task that has a fairly good possibility of failure. What is the best way to handle something going wrong? (Assuming I know what the problem is).
For example lets say I have a function that reads a two byte string and returns it:
#include <stdio.h>
#include <stdlib.h>
char *bar(void)
{
char *foo = malloc(3);
scanf("%2s", foo);
return foo;
}
int main(void)
{
char *foo = bar();
puts(foo);
free(foo);
return 0;
}
The above example has absolutely no error handling whatsoever. There are two ways that I would implement some sort of error handling, but I’m not sure which would be more preferred or considered best practice.
Method 1 (print error message To stderr from within the function):
#include <stdio.h>
#include <stdlib.h>
char *bar(void)
{
char *foo;
if(!(foo = malloc(3)))
{
fputs("\nError! Memory allocation failed.", stderr);
return 0x00;
}
scanf("%2s", foo);
return foo;
}
int main(void)
{
char *foo;
if(!(foo = bar())) return 1;
puts(foo);
free(foo);
return 0;
}
Method 2 (print error message to stderr from the calling function):
#include <stdio.h>
#include <stdlib.h>
char *bar(void)
{
char *foo;
if(!(foo = malloc(3))) return 0x00;
scanf("%2s", foo);
return foo;
}
int main(void)
{
char *foo;
if(!(foo = bar()))
{
fputs("\nError! Memory allocation failed.", stderr);
return 1;
}
puts(foo);
free(foo);
return 0;
}
I’m almost thinking that method two would be the best way to go because that way I could get more specific with my error messages depending on what I’m calling that function for at the time.
What I worry about with method two is the fact that I lose the ability to print what specifically went wrong in the function if it has more than one potential point of failure.
Pseudo Code:
IF FAILUREA
PRINT "FAILUREA OCCURED"
RETURN
IF FAILUREB
PRINT "FAILUREB OCCURED"
RETURN
This wouldn’t be much of a problem if the function I was calling was an int because then I could just return a different integer value based on what went wrong. But in the case of a char* I typically try to return NULL on failure (so both FAILUREA and FAILUREB would be returning NULL); there would be no way to know what caused the function to fail.
So my question is what is best practice when it comes to handling error messages?
Allowing the caller to handle error reporting is better because:
stderrmay not be available and an alternative reporting mechanism is required.bar()as an actual failure and have no need to report it.If a function has multiple possible failure reasons then a possibility is to pass an argument to the function that is updated in the event of failure. The calling function can then choose an appropriate action depending on the actual failure reason. For example: