Is it a bad practice to output error messages in a function with one input and one output [closed] - c

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 9 years ago.
Improve this question
I was once told that functions with one input and one output(not exactly one) should not print messages when being called. But I don't understand. Is it for security or just for convention?
Let me give an example. How to deal with an attempt that access data in a sequential list with an incorrect index?
// 1. Give out the error message inside the function directly.
DataType GetData(seqList *L, int index)
{
if (index < 0 || index >= L->length) {
printf("Error: Access beyond bounds of list.\n");
// exit(EXIT_FAILURE);
}
return L->data[index];
}
// 2. Return a value or use a global variable(like errno) that
// indicates whether the function performs successfully.
StateType GetData(seqList *L, int index, int *data)
{
if (index < 0 || index >= L->length) {
return ERROR;
}
*data = L->data[index];
return OK;
}

I think there are two things going on here:
Any visible and unexpected side-effect such as writing to streams is generally bad, and not just for functions with one input and one output. If I was using a list library, and it started silently writing error messages to the same output stream I was using for my regular output, I'd consider that a problem. However, if you are writing such a function for your own personal use, and you know ahead of time that the action you want taken is always to print a message and exit(), then it's fine. Just don't force this behavior on everyone else.
This is a specific case of the general problem of how to inform callers about errors. A lot of the time, a function cannot know the correct response to an error, because it doesn't have the context that the caller does. Take malloc(), for instance. The vast majority of the time, when malloc() fails, I just want to terminate, but once in a great while I might want to deliberately fill the memory by calling malloc() until it fails, and then proceed to do something else. In this case, I don't want the function to decide whether or not to terminate - I just want it to tell me it's failed, and then pass control back to me.
There are a number of different approaches to handling errors in library functions:
Terminate - fine if you're writing a program yourself, but bad for a general purpose library function. In general, for a library function, you'll want to let the caller decide what to do in the case of an error, so the function's role is limited to informing the caller of the error.
Return an error value - sometimes OK, but sometimes there is no feasible error value. atoi() is a good case in point - all the possible values it returns could be correct translations of the input string. It doesn't matter what you return on error, be it 0, -1 or anything else, there is no way to distinguish an error from a valid result, which is precisely why you get undefined behavior if it encounters one. It's also semantically questionable from a slightly purist point of view - for instance, a function which returns the square root of a number is one thing, but a function which sometimes returns the square root of a number, but which sometimes returns an error code rather than a square root is another thing. You can lose the self-documenting simplicity of a function when return values serve two completely separate purposes.
Leave the program in an error state, such as setting errno. You still have the fundamental problem that if there is no feasible return value, the function still can't tell you that an error has occurred. You could set errno to 0 in advance and check it afterwards every time, but this is a lot of work, and may just not be feasible when you start involving concurrency.
Call an error handling function - this basically just passes the buck, since the error function then also has to address the issues above, but at least you could provide your own. Also, as R. notes in the comments below, other than in very simple cases like "always terminate on any error" it can be asking too much of a single global error handling function to be able to sensibly handle any error that might arise in a way that your program can them resume normal execution. Having numerous error handling functions and passing the appropriate ones individually to each library function is technically possible, but hardly an optimal solution. Using error handling functions in this way can also be difficult or even impossible to use correctly in the presence of concurrency.
Pass in an argument that gets modified by the function if it encounters an error. Technically feasible, but it's not really desirable to add an additional parameter for this purpose to every library function ever written.
Throw an exception - your language has to support them to do this, and they come along with all kinds of associated difficulties including unclear structure and program flow, more complex code, and the like. Some people - I'm not one of them - consider exceptions to be the moral equivalent of longjmp().
All the possible ways have their drawbacks and advantages, as of yet humanity has not discovered the perfect way of reporting errors from library functions.

In general you should make sure you have a consistent and coherent error handling strategy, which means considering whether you want to pass an error up to a higher level or handle it at the level it initially occurs. This decision has nothing to do with how many inputs and outputs a function has.
In a deeply embedded system where a memory allocation failure occurs at a critical juncture, for example, there's no point passing that error back up (and indeed you may well not be able to) - all you can do might be enter a tight loop to let the watchdog reset you. In this case there's no point reserving invalid return values to indicate error, or indeed in even checking the return value at all if it doesn't make sense to do so. (Note I am not advocating just lazily not bothering to check return values, that is a different matter entirely).
On the other hand, in a lovely beautiful GUI app you probably want to fail as gracefully as possible and pass the error up to a level where it can be either worked around / retried / whatever is appropriate; or presented to the user as an error if nothing else can be done.

It is better to use perror() to display error messages rather than using printf()
Syntax:
void perror(const char *s);
Also error messages are supposed to be sent to the stderr stream than stdout.

Yes, it's a bad practice; even worse is that you're sending the output to stdout rather than stderr. This could end up corrupting data by mixing error message in with output.
Personally, I believe very strongly that this kind of "error handling" is harmful. There is no way you can validate that the caller passed a valid value for L, so checking the validity of index is inconsistent. The documented interface contract for the function should simply be that L must be a valid pointer to an object of the correct type, and index a valid index (in whatever sense is meaningful to your code). If an invalid value for L or index is passed, this is a bug in your code, not a legitimate error that can occur at runtime. If you need help debugging it, the assert macro from assert.h is probably a good idea; it makes it easy to turn off the check when you no longer need it.
One possible exception to the above principle would be the case where the value of L is coming from other data structures in your program, but index is coming from some external input that's not under your control. You could then perform an external validation step before calling this function, but if you always need the validation, it makes sense to integrate it like you're doing. However, in that case you need to have a way to report the failure to the caller, rather than printing a useless and harmful message to stdout. So you need to either reserve one possible return value as an error sentinel, or have an extra argument that allows you to return both a result and an error status to the caller.

Return a reserved value that's invalid for a success condition. For example, NULL.
It is advisable not to print because:
It doesn't help the calling code reason about the error.
You're writing to a stream that might be used by higher level code for something else.
The error may be recoverable higher, so you might be just printing misleading error messages.
As others have said, consistency in how you deal with error conditions is also an important factor. But consider this:
If your code is used as a component of another application, one that does not follow your printing convention, then by printing you're not allowing the client code to remain faithful to its own strategy. Thus, using this strategy you impose your convention to all related code.
On the other hand, if you follow the "cleaner" solution of returning a reserved value and the client code wants to follow the printing convention, the client code can easily adapt to what you return and even print an error, by making simple wrappers around your functions. Thus, using this strategy you give the users of your code enough space to choose the strategy that best works for them and to be faithful to it.

It is always best if code deals with one thing only. It is easier to understand, it is easier to use, and is applicable in more instances.
Your GetData function that prints an error message isn't suitable for use in cases where there may not be a value. i.e. The calling code wants to try to get a value and handle the error by using a default if it doesn't exist.
Since GetData doesn't know the context it can't report a good error message. As an example higher up the call stack we can report hey you forgot to give this user an age, vs in GetData where all it knows is we couldn't get some value.
What about a multithreaded situation? GetData seems like it would be something that might get called from multiple threads. With a random bit of IO shoved in the middle it will cause contention over who has access to the console if all the threads need to write at the same time.

Related

C function error: is it better to abort the function or simply exit the program?

The title says it all. Since C doesn't have exceptions, I'm not exactly sure how to handle errors. I've thought of the advantages and disadvantages of both:
ABORTING:
Basically what I mean by this is to return an error code (which will be declared in a .h file, maybe with its own perror()-like function) and abort the function, and the obvious advantage is that it helps the user do error-handling, but the disadvantages are:
If the function is not checked every time after it is executed for an error, and an error does indeed occur, it could cause big problems as the program progresses and the user will have a hard time finding where the issue is coming from.
Looking through the header file for the error codes can be tough and annoying.
Error codes may conflict with error codes in other libraries or the builtin C error codes.
EXIT THE PROGRAM:
Pretty self-explanatory: as soon as an error is found, print the error to stderr and exit. The advantage of this is that if the error message is detailed enough, the user will easily know what is wrong with their code and fix it, but the main disadvantage is that the user will not be able to write any code that could handle a possible error and would instead have to change the code itself (and it becomes a bigger problem when you need to ask for input or something similar, in which there are millions of possible errors that could arise from incorrect input).
This largely depends on what your program is doing. Some programs such as simple command line utilities will just abort on invalid input for example, without affecting much neither the user experience, nor the system stability. The user will simply correct themselves and rerun. On the other hand, if it is a safety-critical system, such as military, medical or transportation equipment (read autopilot, pacemaker and such) aborting its program will cost human lives. Or as suggested in the comments - a simple word processor. The user might be very unsatisfied if they loose all their work after made some stupid mistake which caused some program error.
So the general approach to writing a robust software would be to classify your errors as fatal and non-fatal. Non-fatal are the ones you can anticipate during normal program run and can be gracefully handled in a way which allows the program to continue. Fatal ones are the ones which are caused by some abnormal conditions (hardware failure, missing components and such) which make the program not to be able to continue.
Depending on the system nature you might want to loosen or tighten the above classification.
Return a proper error code from that function. Otherwise it would be hard to use that function in a different context, like a unit test. Also it wouldn't be possible for the calling program to cleanup it's resources or, simply print an error message.

Error management for a C computer game [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 9 years ago.
Improve this question
What kind of errors should I expect with a computer game written in C and how to handle them? With computer game I imply a program where there is no danger of any kind to human lives or "property".
I would like to add as few error handling code as necessary to keep everything as clear and simple as possible. For example I do not want to do this, because this is much simpler and sufficient for a game.
Up to now I have thought about this:
Error: out-of-memory when calling malloc.
Handling: Print error message and call exit(EXIT_FAILURE); (like this)
Error: A programming error, i.e. something which would work if implemented correctly.
Handling: Use assert to detect (which aborts the program if failed).
Error: Reading a corrupted critical file (e.g. game resource).
Handling: Print error message and call exit(EXIT_FAILURE);
Error: Reading a corrupted non-critical file (e.g. load a saved game).
Handling: Show message to user and ask to load another file.
Do you think this is a reasonable approach? What other error should I expect and what is a reasonable minimal approach to handle them?
You can expect at least those errors to happen as mentioned in the documentation to the libraries you use. For a C program that typically is libc at least.
Check the ERRORS section of the man-pages for the functions you'd be using.
I'd also think this over:
I do not want to do this, because this is much simpler and sufficient for a game.
Imagine you'd have fought yourself through a dozen game-levels and then suddenly the screen is gone with an odd OOM*1-error message. And ... - you didn't save! DXXM!
*1 Out-Of-Memory
As I've already stated in the comment I think this is a very broad question. However, it's Xmas and I'll try and be helpful (lest I upset Santa).
The general best practices have been given in the answers posted by #alk and #user2485710. I will try and give a generic boiler-plate for error handling as I see it in C.
You can't guard against everything without writing perfect code. Perfect code is unreachable (kind of like infinity in calculus) though you can try and get close.
If you try to put too much error handling code in, you will be affecting performance. So, let me define what I will call a simple function and a user function.
A user function is a function that can return an error value. e.g. fopen
A simple function is a function that can not return an error value. e.g.
long add(int a, int b)
{
long rv = a; // #alk - This way it shouldn't overflow. :P
return rv + b;
}
Here are a couple rules to follow:
All calls to user functions must handle the returned errors.
All calls to simple functions are assumed safe so no error handling is needed.
If a simple function's parameter is restricted (i.e. an int parameter that must be between 0 and 9) use an assert to ensure its validity (unless the value is the result of user input in which case you should either handle it or propagate it making this a user function).
If a user function's parameter is restricted and it doesn't cause an error do the same as above. Otherwise, propagate it without additional asserts.
Just like your malloc example you can wrap your user functions with code that will gracefully exit your game thereby turning them into simple functions.
This won't remove all errors but should help reduce them whilst keeping performance in mind. Testing should reduce the remaining errors to a minimum.
Forgive me for not being more specific, however, the question seems to ask for a generic method of error handling in C.
In conclusion I would add that testing, whether unit testing or otherwise, is where you make sure that your code works. Error handling isn't something you can plan for in its entirety because some possible errors will only be evident once you start to code (like a game not allowing you to move because you managed to get yourself stuck inside a wall which should be impossible but was allowed because of some strange explosive mechanics). However, testing can and should be planned for because that will reveal where you should spend more time handling errors.
My suggestion is about:
turning on the compiler's flags for raising errors and warning, make your compiler as much pedantic as possible, -Wall, -Werror, -Wextra, for example are a good start for both clang and gcc
be sure that you know what undefined behaviour means and what are the scenarios that can possibly trigger an UB, the compiler doesn't always helps, even with all the warnings turned on.
make your program modular, especially when it comes to memory management and the use of malloc
be sure that your compiler and your standard library of choice both support the C standard that you pick

How to number my Custom errnos

I return a error code if my program was abnormally terminated (via exit()). For standard situations, I just return the underlying errno (for example, ENOMEM for failed mallocs etc). There are, however, also cases when I'll have to terminate due to my own reasons for which there are no system errnos defined.
What error values should I return so that they do not clash with the existing ones. Or am I doing the whole thing assbackwards?
edit: I am sorry if I was not clear with the question. I am not talking about enum etc (they are the mechanism for defining error codes). I was talking of the range of values they could take without clashing with the standard ones.
What I didn't know was that the program can only return 8 bit statuses. So it seems like #r is correct - that is a bit too small to accomodate maybe even all the standard ones, let alone my custom errors. so 1/0 it is :)
The width of the return code is usually pretty small, for example limited to 8 bits, so it's hard to store a lot of information in it. Really I wouldn't bother with exit codes besides 0/1 (success/failure) unless your program is intended for use in shell scripting, in which case you probably just need to figure out the error cases a potential shell script might need to check for and distinguish them (for example, "no match" versus "resource exhausted while searching").
What error values should I return so that they do not clash with the existing ones. Or am I doing the whole thing assbackwards?
Keep it simple. The most important test for error codes (that is also valid for plain functions) is what the caller can do about it. I have seen projects were people were introducing hundreds/thousands error code for all unique cases what in the end led to the total mess in the error handling (they were trying to give every function/SQL statement a unique exit code). And that - error handling - is precisely the party concerned with the exit codes.
My personal rule for return codes is to make sure that they are useful to the error handling. To exemplify, for a batch program I might have peeked the status codes like that:
0 - O.K.,
1 - internal but probably recoverable error (e.g. memory allocation error, kill other batches and try to restart),
2 - fatal error in config (restart will not help),
3 - fatal error in input data (replace input, try again),
4 - output got disk full error (clean /tmp, try again).
That is only an example to highlight that the error codes should be thought about from POV of the caller, not callee. If for example, full/partial automation isn't a target and users have to analyze log files anyway, then returning 0 or 1 would also suffice.
Have you considered using enum to define error codes?
Anyway, here is an interesting discussion about it.
There are few ways to do it.
1) Enums - This can be done in the following way. There is flexibility to add different error codes as and when you need and put them in a group. Say errors related to user authentication, file access, API errors etc.
enum
{
ERROR_GROUP_1 =100,// This gives 99 error codes for a particular group, can be initialised to negative value too.
GROUP1_1,
.
.
ERROR_GROUP_2 = 200
GROUP2_2,
.
.
and so on
};
2) Use pre-processor directives
#define ERROR_CODE_START 00000000L
#define ERROR_CODE_1 (ERROR_CODE_START + 1)
3) Negative return values as int but this will be lot of pain as the reference should be well documented for the values.
4) You can create a structure like GError. Pass a reference to this structure in every API and fill this. If its not NULL then the caller can check the error code and string which will be set in the API.
On a Posix compliant system, there is absolutely no point in returning any number outside the range 0 to 255. This is because the wait() system call only lets you have the bottom eight bits of the return value of your program (or possibly 16 bits).
In practice, you probably just want a handful of codes, maybe just 0 and 1. Further information can be communicated via stderr in a more useful (to a human) text format.

return from 1 point in function [duplicate]

This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Should a function have only one return statement?
Hello,
gcc 4.4.4 c89
Is it good programming practice to return from 1 point in a function.
I have written a function below. However, I am returning from 2 possible points.
Is this good style?
static int init_data(struct timeout_data_t *timeout_data)
{
if(timeout_data == NULL) {
fprintf(stderr, " [ %s ] [ %d ]\n",
__func__, __LINE__);
return FALSE;
}
/* Assign data */
timeout_data->seconds = 3;
timeout_data->func_ptr = timeout_cb;
return TRUE;
}
If it aids readability, then there is nothing wrong with it.
Personally, I write this kind of code all of the time.
This is an ongoing religious-style debate without an accepted answer. There are many people on both sides of the argument, who feel strongly about it.
I don't think there's anything wrong with it personally, but the best approach is to go with the style guidelines of your team, if they have some (and if not, just ask about it. If anyone recoils in horror, it would be kinder to stick to single-return-point).
I've had managers that lived and died by the 1 return policy for the sake of "readability", even though it's much more readable in some cases without it.
The bottom line is... if the man that signs your paycheck says you're only going to use 1 return, use 1 return. The best way to do this is
type myfunc(params) {
type result = defaultValue;
// actual function here, word for word
// replace "return $1" with "result = $1"
return result;
}
This is a valid way to do things in their book, and will smile at your 1 return policy adherence. Of course, you know using this adds ZERO readability because all you've done is replace "return" (which is syntax highlighted) with "result =" which is not. But you've made your boss happy, which when you break it all down is what development is about anyway, right? :-)
In straight C, I think that error checking/parameter verification at the top of the function with a return (or possibly even multiple return points in the parameter verification) results in reasonably clean code. After that point, though, my opinion is that it is a good idea to have one single return at the bottom of the function. That helps avoid problems with cleanup (e.g., freeing of memory) that might be allocated in the workings of the function.
There's nothing inherently wrong about having more than one exit point, especially when you're returning on errors. Returning immediately usually makes for clearer code than having the whole thing wrapped in an if/else statement and setting some result flag to be returned at the end. (When you see "return result;", you have to look through all of the earlier code to see how and when result gets set. More moving parts == less clarity.)
You've tagged your questions as "C" which makes a difference.
In C you might write code such as
open file
process data
close file
If you put a return in the middle of the process data section then you're likely to skip the essential cleanup so it might be considered bad practice to have multiple return points because it's very easy to mess up.
If it was C++ then its best practice to let destructors handle cleanup so it's not nearly such a potential problem so this advice is somewhat obsolete in c++
As Oded and Andrzej Doyle pointed out there is nothing wrong with it.
They is no such thing as a golden rule when it comes to this.
The first an most important thing you have to keep in mind when writing code is that some one else will have to read it and make sense out of it. Maybe you will have to go about it in a couple of months, and if you have made a mess you will regret it.
Personally I always:
if the code is new used the coding style everybody else is using in the project.
If editing others code used the coding style already implemented there.
Avoid above all code optimizations (the compiler is best at that).
keep it clean and lean.
If your function is small enough (10-15 lines), as it should be :), then it really doesn't matter if you use a single return point or multiple one. Both are equally readable.
Problems start cropping up with badly designed large functions. In such cases both the styles, returning from a single point, and returning from multiple points, further complicates the function, although even in such cases I prefer returning early and returning at multiple points.
It's often the case that you have to check for several conditions etc before you start with the real work, and then you are tempted to do an early return, as in your code. I think this is fine for short methods, but when it gets more complicated I'd suggest to break your code in a "setup and check" method and a "real work" method, both having only one exit. Of course as long as it's readeable, it's fine to have multiple returns (e.g. in a long switch statement).
Failing (and thus returning) early is a very very very good practice. All the code after the checks is free of a lot of potential errors.

What should I return for errors in my functions in C?

Currently I'm returning -1 in my custom functions in C if something wrong happens and 0 for success. For instance, working with a linked list and some function needs a non-empty list to work properly. If the list passed as argument is empty, I return -1 (error) and 0 if it's not empty and the function worked without a problem.
Should I, maybe, return 1 instead of -1?
Is this the standard way of doing things in C or do you recommend a different approach?
Return a non-zero value to indicate failure. This way you can write you functions calls as so:
if(func_call())
{
doErrorHandling();
}
This convention will allow you to use any !0 value to indicate a specific error, and this will allow you to use one variable in a uniform fashion. So the body of the if shown in the example above can then have a switch statement to process the specific errors.
You can do it differently -- but if you choose to do so stick to a convention -- the win32 API (and other API's I have used) mix and match conventions unfortunately.
That sounds fine. -1 is used in I/O function because a positive return value usually means success and is the number of bytes that were processed. If you have multiple ways a function can go wrong, then you can either return different integers or set a global error variable (errno is used by the standard library) to contain the error code.
In terms of style, I prefer not to return status codes as it means my functions can't (cleanly) return anything else. Instead I would check the input before calling the function. But this is subjective and depends on the context.
I suggest that you find a way to format a fully-informative human-readable string at the point of the error, where all information is still available, and design a way to get it down thru the rest of the program, thru the user, his mobile phone, to your development team for the analysis.
This seems to me like an important feature of any design, if you want to produce better software faster. Killing error information on the way is a major crime, and C language is no excuse.
There are many schemes - but whatever you do, do it consistently!
If you don't have many failing conditions, just use 0 for error. That's because error tests are written in a simple way:
if (!list_insert(...)) { handle_error; }
Otherwise below-zero answers are good to use along with normal answers >= 0. You can use this for functions like list length, which in normal conditions will not be negative. Or if you want many error codes (-1 - nonexistant, -2 - not found, -3 ..., ...)

Resources