Versions Compared

Key

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

Wiki Markup
The return values for {{malloc()}} and other C memory allocation routines indicate the failure or success of the allocation. According to C99, {{calloc()}}, {{malloc()}}, and {{realloc()}} return null pointers if the requested memory allocation fails \[[ISO/IEC 9899:1999|AA. C++ References#ISO/IEC 9899-1999]\]. Failure to detect and properly handle memory management errors can lead to unpredictable and unintended program behavior. As a result, it is necessary to check the final status of memory management routines and handle errors appropriately.

The following table shows the possible outcomes of the standard memory allocation functions.

Function

Successful Return

Error Return

malloc()

pointer to allocated space

null pointer

calloc()

pointer to allocated space

null pointer

realloc()

pointer to the new object

null pointer

...

By default operator new will throw a std::bad_alloc exception if the allocation fails. Therefore you need not check that the result of operator new is NULL. However, to ease conversion of code to C++, the C++ Standard ISO/IEC 14882-2003 provides a variant of operator new that behaves like malloc():

Code Block

char* s = new char[-1]; // throws a std::bad_alloc exception
char* s = new (std::nothrow) char[-1]; // returns NULL

When using std::nothrow, it is imperative to check that the return value is not NULL before using it.

Noncompliant Code Example (malloc())

In this example, input_string is copied into dynamically allocated memory referenced by str. However, the result of malloc() is not checked before str is referenced. Consequently, if malloc() fails, the program abnormally terminates.

Code Block
bgColor#FFcccc
char *input_string;

/* initialize input_string */

size_t size = strlen(input_string) + 1;
char *str = (char *)malloc(size);
strcpy(str, input_string);
/* ... */
free(str);
str = NULL;

Noncompliant Code Example (std::nothrow)

This example remains noncompliant if we replace malloc() with new(std::nothrow).

Code Block
bgColor#FFcccc

char *input_string;

/* initialize input_string */

size_t size = strlen(input_string) + 1;
char *str = new(std::nothrow) char[size];
strcpy(str, input_string);
/* ... */
delete[] str;
str = NULL;

Compliant Solution

...

(std::nothrow)

With std::nothrow, the new operator The malloc() function as well as the other memory allocation functions, returns either a null pointer or a pointer to the allocated space. Always test the returned pointer to ensure it is not NULL before referencing the pointer. Handle the error condition appropriately when the returned pointer is NULL.

Code Block
bgColor#ccccff
char *input_string;

/* initialize input_string */

size_t size = strlen(input_string) + 1;
char *str = new(char *)malloc(size)std::nothrow) char[size];
if (str == NULL) {
  /* Handle allocation error */
}
else {
  strcpy(str, input_string);
  /* ... */
  delete[] free(str);
  str = NULL;

Noncompliant Code Example

}

Compliant Solution (bad_alloc)

Alternatively, one can use operator new without std::nothrow. Unless std::nothrow is provided, operator new never returns NULL; it will instead throw a std::bad_alloc exception if it cannot allocate memoryThis noncompliant code example calls realloc() to resize the memory referred to by p. However, if realloc() fails, it returns a null pointer. Consequently, the connection between the original block of memory and p is severed, resulting in a memory leak.

Code Block
bgColor#FFcccc#ccccff
voidchar *p;
size_t new_sizeinput_string;

/* initialize newinput_sizestring */

p = realloc(p, new_size);
if (p == NULL)   {
 /* Handle error */
}

When using realloc(), it is important to account for zero-byte allocations (see MEM04-CPP. Do not perform zero length allocations).

Compliant Solution

In this compliant solution, the result of realloc() is assigned to the temporary pointer q and validated before assigning it to the original pointer p.

Code Block
bgColor#ccccff

void *p;
void *q;
size_t new_size;

/* initialize new_size */

q = realloc(p, new_size);
if (q == NULL)   {
 /* Handle error */
}
else {
  p = q;
}size_t size = strlen(input_string) + 1;
char *str = new char[size];
strcpy(str, input_string);
/* ... */
delete[] str;
str = NULL;

Risk Assessment

Failing to detect allocation failures can lead to abnormal program termination and denial-of-service attacks.

...

Wiki Markup
\[[ISO/IEC 9899:1999|AA. C++ References#ISO/IEC 9899-1999]\] Section 7.20.3, "Memory management functions"
\[[ISO/IEC 14882-2003|AA. C++ References#ISO/IEC 14882-2003]\] Section 5.3.4
\[[MITRE 07|AA. C++ References#MITRE 07]\] [CWE ID 476|http://cwe.mitre.org/data/definitions/476.html], "NULL Pointer Dereference," and [CWE ID 252|http://cwe.mitre.org/data/definitions/252.html], "Unchecked Return Value"
\[[Seacord 05|AA. C++ References#Seacord 05]\] Chapter 4, "Dynamic Memory Management"
\[[VU#159523|AA. C++ References#VU#159523]\]

...