FREERTOS V11.2.0 · MEMORY

FreeRTOS heap_4: 여유 메모리가 있어도 할당이 실패하는 이유

총 여유량, 가장 큰 빈 블록, 관리 정보와 정렬 비용을 구분합니다.

어느 할당자를 쓰는지 먼저 확인합니다

FreeRTOS heap_4는 주소 순서로 관리하는 빈 블록 중 요청을 만족하는 첫 블록을 사용하고, 해제 때 인접한 빈 블록을 합칩니다. 이것은 heap_2의 best-fit이나 C 라이브러리 malloc과 같은 구현이라는 뜻이 아닙니다. 제품의 malloc이 pvPortMalloc으로 연결되는지는 빌드와 wrapper를 확인해야 합니다.

FreeRTOS 공식 책: 메모리 관리

요청한 바이트보다 큰 블록이 필요합니다

V11.2.0의 pvPortMalloc은 요청 크기에 정렬된 BlockLink_t 관리 정보 크기를 더하고, 다시 portBYTE_ALIGNMENT에 맞춥니다. 따라서 가장 큰 빈 블록의 크기를 그대로 최대 payload라고 부르면 안 됩니다. vPortGetHeapStats의 largest 값은 free-list의 xBlockSize를 읽은 값입니다.

계산 예시로 요청 1,024바이트, 관리 정보 8바이트, 정렬 8바이트를 가정하면 필요한 블록은 1,032바이트입니다. 이 8바이트 값은 설명용 가정이지 모든 포트의 고정값이 아닙니다. 여유 총합이 더 커도 어느 빈 블록도 1,032바이트에 못 미치면 이 요청은 들어가지 않습니다.

분기와 관측 지점을 나눈 자체 개념도
  1. 요청 payload + 포트별 관리 정보

  2. 정렬한 필요 크기와 가장 큰 빈 블록 비교

  3. 적합한 블록 없음 → 총합과 무관하게 실패 가능

FreeRTOS V11.2.0 heap_4.c

현재 값과 과거 최저값을 구분합니다

현재 여유 총량, 가장 큰 빈 블록, 빈 블록 개수와 minimum-ever를 함께 기록합니다. minimum-ever는 실행 중 관측된 최저 여유량이지 지금의 여유량이 아닙니다. vPortGetHeapStats는 빈 목록 순회와 일부 카운터 읽기를 다른 구간에서 수행하므로, 정밀 비교 실험에서는 관련 할당 작업을 멈춘 동일 상태에서 채집하거나 시각 차이를 고려합니다.

중간의 살아 있는 할당은 양옆의 빈 블록 병합을 막습니다. 전부 해제한 한 시험에서 다시 큰 블록이 생겼다고 해서 다른 실행 경로에도 누수가 없는 것은 아닙니다. 요청 크기·성공 여부·반환 책임·생존 기간을 같이 추적해야 합니다.

사례 수치를 재현 결과로 쓰지 않습니다

Jacob Beningo의 단편화 사례는 문제 설정에 참고했지만 원본 애니메이션이나 allocator 연결을 재현하지 않았습니다. 사례의 ring offset, 최종 여유량과 모든 8KiB heap의 용량을 동일시하지 않습니다. 이 글의 계산은 명시한 가정으로 만든 예시이며 실제 보드 측정값이 아닙니다.