Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

The argument to malloc() can be any value of (unsigned) type size_t. If the program uses the allocated storage to represent an object (possibly an array) whose size is greater than the requested size, the behavior is undefined. The implicit pointer conversion lets this slip by without complaint from the compiler.

For example:

Code Block
bgColor#FFcccc#ffcccc
#include <stdlib.h>

typedef struct gadget gadget;
struct gadget {
  int i;
  double d;
};

typedef struct widget widget;
struct widget {
  char c[10];
  int i;
  double d;
};

widget *p;

/* ... */

p = malloc(sizeof(gadget)); /* imminent problem */
if (p != NULL) {
  p->i = 0;               /* undefined behavior */
  p->d = 0.0;             /* undefined behavior */
}

...

quietly assigns p to point to storage too small for a widget. The subsequent assignments to p->i and p->d will most likely produce memory overruns.

Compliant Solution

Casting the result of malloc() to the appropriate pointer type enables the compiler to catch subsequent inadvertent pointer conversions. When allocating individual objects, the "appropriate pointer type" is a pointer to the type argument in the sizeof expression passed to malloc(). This approach is applied in the following code example:

In this code example, malloc() allocates space for a gadget and the cast immediately converts the returned pointer to a gadget *:

code
Code Block
bgColor#ffcccc
widget *p;

/* ... */

p = (gadget *)malloc(sizeof(gadget)); /* invalid assignment */

Here, malloc() allocates space for a gadget and the cast immediately converts the returned pointer to a gadget *. This lets the compiler detect the invalid assignment, because it attempts to convert a gadget * into a widget *. The problem can now be easily identified and corrected:

Compliant Solution (hand-coded)

The compliant solution repeats the same type in the sizeof expression and the pointer cast.

Code Block
bgColor#ccccff
widget *p;

/* ... */

p = (widget *)malloc(sizeof(widget)); /* invalid assignment */

Compliant Solution (macros)

Repeating the same type in the sizeof expression and the pointer cast is easy to do, but still invites errors. Packaging the repetition in a macro, such as

...