Chapter 25 of ‘Getting Started with FreeRTOS’: Practical Memory Leak Detection

Table of Contents

    • Course Objectives
    • 1. Custom malloc/free Hook Functions
      • 1.1 Basics of FreeRTOS Memory Management
      • 1.2 Principles of Hook Function Implementation
      • 1.3 Practical: Implementation of Memory Tracking Hook
    • 2. Memory Fragmentation Monitoring Solutions
      • 2.1 Causes of Memory Fragmentation
      • 2.2 Fragmentation Detection Methods
      • 2.3 Comparison Table of Optimization Strategies
    • Practical Project: Memory Monitoring System
      • 3.1 Functional Requirements
      • 3.2 Key Data Structures
      • 3.3 Implementation of Monitoring Tasks
    • Troubleshooting Guide for Common Issues
    • Post-Class Exercises
    • Further Reading

Chapter 25 of 'Getting Started with FreeRTOS': Practical Memory Leak Detection

Course Objectives

  1. Master the FreeRTOS memory management mechanism
  2. Implement custom malloc/free hook functions
  3. Learn memory fragmentation monitoring solutions
  4. Master debugging methods for common memory issues

1. Custom malloc/free Hook Functions

1.1 Basics of FreeRTOS Memory Management

// Five memory management schemes provided by FreeRTOS
1. heap_1.c - Static allocation, no release
2. heap_2.c - Best-fit algorithm, does not merge free blocks
3. heap_3.c - Encapsulates standard library malloc/free
4. heap_4.c - Best-fit + merge free blocks
5. heap_5.c - Supports non-contiguous memory regions

1.2 Principles of Hook Function Implementation

// Enable hooks in FreeRTOSConfig.h
#define configUSE_MALLOC_FAILED_HOOK 1

// Prototype for memory allocation failure hook function
void vApplicationMallocFailedHook(void);

// Memory allocation statistics functions
size_t xPortGetFreeHeapSize(void); // Get current free memory
size_t xPortGetMinimumEverFreeHeapSize(void); // Get historical minimum free memory

1.3 Practical: Implementation of Memory Tracking Hook

// Memory operation record structure
typedef struct {
    void *ptr;
    size_t size;
    const char *file;
    int line;
} MemRecord;

// Memory allocation wrapper function
void *debug_malloc(size_t size, const char *file, int line) {
    void *ptr = pvPortMalloc(size);
    if (ptr) {
        record_allocation(ptr, size, file, line); // Record allocation
    }
    return ptr;
}

// Memory deallocation wrapper function
void debug_free(void *ptr, const char *file, int line) {
    record_deallocation(ptr, file, line); // Record deallocation
    vPortFree(ptr);
}

// Macro definitions to simplify calls
#define MALLOC(size) debug_malloc(size, __FILE__, __LINE__)
#define FREE(ptr) debug_free(ptr, __FILE__, __LINE__)

2. Memory Fragmentation Monitoring Solutions

2.1 Causes of Memory Fragmentation

  • Frequent allocation/release of memory of different sizes
  • Defects in memory allocation algorithms
  • Cumulative effects after long-term operation

2.2 Fragmentation Detection Methods

// Get memory fragmentation rate
float get_memory_fragmentation() {
    size_t free_size = xPortGetFreeHeapSize();
    BlockStats_t stats;
vPortGetHeapStats(&stats);

    if (stats.xAvailableHeapSpaceInBytes == 0)
        return 0.0f;

    return 1.0f - (float)free_size / stats.xAvailableHeapSpaceInBytes;
}

// Periodically print memory status
void check_memory_task(void *pv) {
    while (1) {
        printf("Free: %u, MinEver: %u, Frag: %.2f%%\n",
               xPortGetFreeHeapSize(),
               xPortGetMinimumEverFreeHeapSize(),
               get_memory_fragmentation() * 100);
        vTaskDelay(pdMS_TO_TICKS(5000));
    }
}

2.3 Comparison Table of Optimization Strategies

Strategy Advantages Disadvantages Applicable Scenarios
Fixed Block Memory Pool No fragmentation Poor flexibility Fixed-size objects
Periodic Restart Simple and direct Affects availability Non-critical tasks
Memory Compaction Significant effect Complex implementation Long-running systems

Practical Project: Memory Monitoring System

3.1 Functional Requirements

  1. Real-time display of memory usage
  2. Detect memory leaks and locate them
  3. Fragmentation warning
  4. Historical data recording

3.2 Key Data Structures

typedef struct {
    uint32_t total_allocs;
    uint32_t total_frees;
    uint32_t current_usage;
    uint32_t peak_usage;
    MemRecord active_blocks[MAX_RECORDS];
} MemoryMonitor;

3.3 Implementation of Monitoring Tasks

void memory_monitor_task(void *pv) {
    MemoryMonitor *monitor = init_memory_monitor();

    while (1) {
        // Check for leaks (allocated blocks not released)
        check_leaks(monitor);

        // Check fragmentation
        if (get_memory_fragmentation() > 0.7f) {
            trigger_alert(FRAG_ALERT);
        }

        // Generate report
        generate_report(monitor);

        vTaskDelay(pdMS_TO_TICKS(10000));
    }
}

Troubleshooting Guide for Common Issues

  1. Memory Allocation Failure

  • Check xPortGetFreeHeapSize()
  • Confirm if there are memory leaks
  • Consider using heap_4/5 to reduce fragmentation
  • Random Crashes

    • Check for wild pointer access
    • Verify if memory is set to NULL after release
    • Use memory protection features (MPU)
  • Performance Degradation

    • Monitor fragmentation levels
    • Check allocation/release frequency
    • Consider using memory pools instead

    Post-Class Exercises

    1. Implement a memory allocation tracker that records the last 10 memory operations
    2. Write fragmentation test cases to compare the performance differences between heap_2 and heap_4
    3. Design a CLI command for memory leak detection that displays suspicious leak points

    Further Reading

    • Official Documentation on FreeRTOS Memory Management
    • ‘Practical Memory Optimization in Embedded Systems’
    • ARM Cortex-M Memory Protection Unit (MPU) Application Guide

    Leave a Comment