Checkers:UNINIT.HEAP.MUST

From current

Reference > C/C++ checkers > UNINIT.HEAP.MUST

Contents


Heap memory is always uninitialized upon return from the frequently used allocation function: malloc(). This is in contrast to the function calloc() which explicitly initializes all allocated memory. This error indicates that memory allocated with malloc() has not been initialized prior to first usage.

Consequences

Using uninitialized heap memory can result in significant performance irregularities for your code as the values assigned to any given data object are randomly picked from the heap memory allocated and could reflect the state of previously-used objects, of objects from another process, etc. Obviously, heap memory, just like stack content, must be appropriately initialized if reads from that memory are to have the expected effect.

How to address

Ensure that all allocated memory is initialized explicitly in your code, or use the standard calloc() library function to initialize all allocated memory to zero.

Examples

Example 1

1  #include<stdlib.h>
2  
3  typedef struct {
4    int x;
5  } S1;
6  
7  typedef struct {
8    S1* ptr;
9 } S2;
10 
11 void foo(S1* ptr) {
12   int k = ptr ? ptr->x : -1;
13 }
14 
15 int main() {
16   S2* ps = (S2*)malloc(sizeof(S2));
17   if( ps != NULL ) {
18     foo(ps->ptr);
19     free(ps);
20   }
21   return 0;
22 }

Klocwork produces an uninitialized heap memory reading report, indicating that variable 'ps->ptr', which gets its value from the memory allocated at line 16, is used uninitialized at line 18.


Solution 1

1  #include<stdlib.h>
2  
3  typedef struct {
4    int x;
5  } S1;
6  
7  typedef struct {
8    S1* ptr;
9 } S2;
10 
11 void foo(S1* ptr) {
12   int k = ptr ? ptr->x : -1;
13 }
14 
15 int main() {
16   S2* ps = (S2*)calloc(1, sizeof(S2));
17   if( ps != NULL ) {
18     foo(ps->ptr);
19     free(ps);
20   }
21   return 0;
22 }

Here we simply replaced the call to malloc() with a similar call to calloc() in order to be sure that the memory allocated is pre-initialized to zero. This saves us having to manually initialize each element of the 'S2' structure before using the pointer 'ps'.

Example 2

1  #include<stdlib.h>
2
3  typedef struct {
4      int x, y;
5  } S1;
6
7  int foo(S1* ptr) {
8      return ptr->x * ptr->y;
9  }
10
11  int main() {
12     S1* ps = (S1*)malloc(sizeof(S1));
13     if( ps != NULL ) {
14         foo(ps);
15         free(ps);
16     }
17 }

In this case, the memory allocated at line 12 is used uninitialized at line 14.

Solution 2

1  #include<stdlib.h>
2
3  typedef struct {
4      int x, y;
5  } S1;
6
7  int foo(S1* ptr) {
8      return ptr->x * ptr->y;
9  }
10
11 int main() {
12     S1* ps = (S1*)malloc(sizeof(S1));
13     if( ps != NULL ) {
14         ps->x = 32, ps->y = 64;
15         foo(ps);
16         free(ps);
17     }
18 }

Here, rather than using the calloc() function to allocate the memory, we have instead explicitly initialized the members of the structure 'S1' so that when the values are read from the pointer 'ps' they are already known to be valid.

Related checkers

External guidance