In this section:

Overview

This problem can occur when a block of memory contains a pointer to another dynamically allocated block, as indicated in the following figure.

If the main memory block is freed its memory becomes invalid, which means that the included pointer can no longer be used to free the second block. This causes a permanent memory leak.

CodeDescriptionEnabledReportedPlatform
LEAK_ASSIGN

Memory leaked freeing block

(tick)RuntimeWindows/Unix


Problem

The following code defines PB to be a data structure that contains a pointer to another block of memory.

/*
 * File: leakfree.c
 */
 #include <stdlib.h>

typedef struct ptrblock {
	char *ptr;
	} PB;

main()
	{
		PB *p;

		p = (PB *)malloc(sizeof(*p));
		p->ptr = malloc(10);

		free(p);
		return (0);
	}

We first create a single PB and then allocate a block of memory for it to point to. The call to free on PB then causes a permanent memory leak because it frees the memory containing the only pointer to the second allocated block. This latter block can no longer be freed.

Diagnosis at Runtime

[leakfree.c:17] **LEAK_FREE**
>>			 free(p);
Memory leaked freeing block: p->ptr

---- Associated Common Weakness Enumerations ----
CWE-119: Improper Restriction of Operations within the Bounds of a Memory Buffer
CWE-400: Uncontrolled resource consumption
CWE-401: Missing release of memory after effective lifetime
CWE-772: Missing release of resource after effective lifetime

Lost block:		0x00013888 thru 0x00013891 (10 bytes)
				block allocated at:
				malloc() (interface)
					main() leakfree.c, 15
Stack trace where the error occurred:
		main() leakfree.c, 17
  • Line 2: Source file and line at which the problem was detected.
  • Line 3: Description of the problem and the value that is about to be lost.
  • Line 5-9: CWEs associated with this problem.
  • Line 11: Description of the block of memory that is about to be lost, including its size and the line number at which it was allocated.
  • Line 15: Stack trace showing the function call sequence leading to the error.

Repair

In many cases, this problem is caused by forgetting to free the enclosed blocks when freeing their container. This can be corrected by adding a suitable call to free the memory before freeing the parent block. Use caution when doing this, however, to ensure that the memory blocks are freed in the correct order. Changing the example problem in the following manner would still generate the same error because the blocks are freed in the wrong order:

free(p);
free(p->ptr);

The contained blocks must be freed before their parents because the memory becomes invalid as soon as it is freed. Thus, the second call to free in the above code fragment might fail because the value p->ptr is no longer valid. It is legal, for example, for the first call to free to have been set to zero or otherwise destroyed the contents of its memory block. Many systems allow the out of order behavior, although it is becoming less portable as more and more systems move to dynamically re-allocated (moveable) memory blocks.

Some applications may be unable to free memory blocks and may not need to worry about their permanent loss. To suppress these error messages in this case suppress LEAK_FREE.

References

The table below shows Common Weakness Enumerations associated with this error.

CWEDescription
CWE-119Improper Restriction of Operations within the Bounds of a Memory Buffer
CWE-400Uncontrolled resource consumption
CWE-401Missing release of memory after effective lifetime
CWE-772Missing release of resource after effective lifetime
  • No labels