#What should my functions return when invalid parameters are passed?

1 messages · Page 1 of 1 (latest)

granite latch
#

I am writing a linked list implementation in C and I am wondering about how should the functions behave when invalid parameters are passed. I don't know what the common practice is.
For example:

void insert(List* list, int val, int pos);

What should this function do if list is NULL? Or if position is out of bounds?

lofty muskBOT
#

When your question is answered use !solved to mark the question as resolved.

Remember to ask specific questions, provide necessary details, and reduce your question to its simplest form. For tips on how to ask a good question use !howto ask.

gray grail
# granite latch I am writing a linked list implementation in C and I am wondering about how shou...

there is a wider question, as to know whether or not the function is meant to handle such case.

if the pre-conditions of the method is that list should not be null, then calling it with a null pointer is de facto a contract violation. in that case, one can justify that the behavior becomes undefined, and you're free to handle the case however you'd like to handle it (for example, the std uses that paradigm on many functions). in particular, you can assert(list != NULL) to fail-fast in dev mode, and handle the case with a trivial "do nothing" implementation when assertions are off

if your function is meant to be called on NULL (it is part of the pre-conditions to invoke with null), you can still decide whether or not there is a case of error, or if it's fine. for example here, inserting in a null list can be argued to have just no effect at all, and you just return; directly. in any case, the behavior should go in the post-conditions

#

I don't find it shocking to have functions that are well-defined on a subset, and do "whatever" on the effective domain imposed by the language, because the language cannot type correctly pre-conditions. as long as the "whatever" is doing something valid and safe (typically segfaulting is not a valid option)

for example:

void list(List *list, int val, int pos)
{
  {
    /* Guards for input. Post-conditions of the block
     *   - the inputs verify the pre-conditions
     */

    if(!list || pos > list_len(list)) return;
  }

granite latch
#

I also saw something like this on SO:

typedef enum
{
  FOO_OK,
  FOO_ERR_STRLENGTH,
  FOO_ERR_DIVIDE_BY_ZERO,
  ...
} foo_err_t;


foo_err_t  foo_func (/* parameters */)
{
  if (strlen(s) < 1) 
  {
    return FOO_ERR_STRLENGTH;
  }

  ...

  return FOO_OK;
}

Is this a common approach in C?

gray grail
#

it's all about what pre/post conditions you want to guarantee, I think... as long as you keep your invariants correct, I don't see the problem of both approach. they can all be argued against and in favor I think

#

(I heavily dislike enum though, because they pollute way too much. but it's matter of taste I guess)

obsidian bough
#

Only return enums if you truly intend to deal with each case differently.
All too often I see such libs and then also provide a sort of "success" or "fail" function-like macro. E.g.

#define XXX_SUCCESS(val) val == XXX_OK

And then I think, why not return a boolean then?

granite latch
granite latch
gray grail
#

if your pre-conditions are explicitly "don't call with null", it's the user fault to actually do it (it's the strategy used by malloc, free, fflush, ...) ; if people are big boys enough to check error codes and react, they can also pre-validate their inputs: for them, there is literally no difference between the two

granite latch
gray grail
#

yes

#

my opinion at least

granite latch
#

It's also less work on both ends

gray grail
#

and ofc here, it's about "internal contracts", not about user inputs validations. that's another topic (for end users, you usually want a report of what went wrong exactly, and signal that; but here it's not the context I guess)

gray grail
granite latch
#

Okay, thanks @gray grail. I now at least have a clearer idea of how to think about such cases so I will mark this solved.