Naive Local Pointer Update in C

A programmer wanted to implement a C method with an output parameter, that is, a parameter used to pass a value back from the method without using (or used in addition to) the return value of the method.

The programmer mistakenly thought that C supports passing arguments by reference, and implemented createSomethingFromCode with an (supposedly) output parameter ‘error_if_fail’ that passes back an explanation error when it fails to achieve its task:

1   #include <stdio.h>

2   #include “something.h”

3   #include “error.h”
4
5   Something* createSomethingFromCode (int code, Error *error_if_fail)
6   {
7       /* Try to create Something here... */

8       if (/* cannot create Something */) {
9           error_if_fail = createError(“Failed to create Something from code %d”, code);

10          return NULL;

11      }

12      return something;
13   }
14
15   int main (int argc, char *argv[])
16   {
17     int INVALID_CODE = 0xdeadbeef;
18     Error *error = NULL;
19     Something* something = createSomethingFromCode(INVALID_CODE, error);
20     if (something == NULL) {
21       printf("Error: %s", error->message);

22       destroyError(error);

23       return 1;
24     }

25     /* else, use something... */
26     return 0;
27  }

This program gets a null pointer exception whenever executes line 21, because error_if_fail above is not an output parameter neither it reflects the value assigned to it by createSomethingFromCode() after the method returns. This is because C does not support passing arguments by reference and because method parameters are local variables when accessed from the method body.

On createSomethingFromCode invocation the argument given is copied into variable error_if_fail. Updates to variable error_if_fail inside createSomethingFromCode body will only update the copy, not the original variable from where the copy obtained its initial value. Assigning error_if_fail on line 9 assigns a value to createSomethingFromCode’s error_if_fail local variable, not to main’s error variable.

A proper implementation of the intended output parameter would be:

1   #include <stdio.h>

2   #include “something.h”

3   #include “error.h”
4
5   Something* createSomethingFromCode (int code, Error **error_if_fail)
6   {
7       /* Try to create Something here... */

8       if (/* cannot create Something */ && error != NULL) {
9           *error_if_fail = createError(“Failed to create Something from code %d”, code);

10          return NULL;

11      }

12      return something;
13   }
14
15   int main (int argc, char *argv[])
16   {
17     int INVALID_CODE = 0xdeadbeef;
18     Error *error = NULL;
19     Something* something = createSomethingFromCode(INVALID_CODE, &error);
20     if (something == NULL) {
21       printf("Error: %s", error->message);

22       destroyError(error);

23       return 1;
24     }

25     /* else, use something... */
26     return 0;
27  }