STM32 강좌

힙(Heap)에 대한 이해와 힙 크기 설정 방법

힙 영역은 전역변수나 지역변수처럼 항상 지정된 크기의 메모리를 사용하는 경우가 아닌 프로그램 동작 시 동적으로 할당되는 메모리를 위해 지정된 영역을 말합니다. 

 

프로그램이 동작하면서 원하는 크기의 메모리를 사용해야 될 경우가 있는데 이러한 경우를 위해 일정한 크기를 선언해 놓고 프로그램 동작 시 이 영역에서 메모리를 할당해 주는 영역을 힙(Heap)이라고 합니다.

 

힙 메모리는 malloc, free와 같은 함수를 사용합니다. 

malloc함수는 지정된 힙 영역에서 사용자가 원하는 크기의 메모리를 할당하는 함수입니다.

원하는 크기를 할당하면 메모리의 포인터를 리턴하며 사용하고자 하는 메모리의 크기가 남아있는 힙의 크기보다 클 경우 NULL을 리턴합니다.

free함수는 할당된 메모리 영역을 반환하는 함수입니다.

 

동적 메모리 할당은 사용된 메모리의 포인터와 사용된 크기 등이 포함되기 때문에 overhead가 발생될 수 있으며 할당과 해제가 반복되면서 단편화(fragment)가 발생될 수 있습니다.

 

동적 메모리 할당은 다양한 구현 방법이 있으며 IAR Compiler에서는 가장 많이 사용되는 dlmalloc를 사용하고 있습니다.

동적 메모리 할당에 대한 더 자세한 정보는 C dynamic memory allocation 을 참고하시기 바랍니다. 

 

아래는 512Byte를 Heap영역으로 선언한 후 461Byte를 할당할 경우를 보여주고 있습니다.

461Byte를 모두 할당하지 못해 NULL을 반환하는 것을 확인할 수 있습니다.

Test결과 overhead에 의해 460byte까지만 사용할 수 있었습니다.

220f5d5b3a25fe3f18fc6ae70530e7a2_1491404524_8485.png



 

 

또한 큰 메모리를 한번 할당하는 것 보다 작은 크기의 메모리를 여러 번 할당할 경우 overhead에 의해 더 적은 메모리만 사용 가능합니다.

아래 예에서는 10byte씩 메모리를 할당하는 예를 보여주고 있습니다. 10byte씩 할당을 진행하다 30번째에서 메모리를 할당하지 못하였습니다.

총 290byte만 할당되어 위 예제에서 460byte정도 할당이 가능한 것에 비해 할당 가능한 용량이 현저히 줄어들게 됩니다.

220f5d5b3a25fe3f18fc6ae70530e7a2_1491404532_4446.png


 

 

 

이와 같이 동적 메모리 할당은 Overhead와 단편화 등에 의해 사용 가능한 용량에 차이가 있을 수 있습니다.

또한 힙은 프로그램의 동작에 따라 사용될 수도 사용되지 않을 수도 있기 때문에 정확한 크기를 예측하는 것이 어렵습니다.

힙은 프로그램에서 사용되는 크기보다 작게 설정될 경우 메모리가 할당되지 않기 때문에 프로그램이 정상적으로 동작되지 않습니다.

 

IAR EWARM은 힙의 사용량을 확인할 수 있는 함수를 제공하고 있습니다.

제공되는 함수를 사용하여 프로그램에서 사용되는 힙의 크기를 예측할 수 있습니다.

 

메모리 동적 할당 관련 라이브러리 사용

IAR에서 제공하는 관련 라이브러리를 사용하기 위해서는 다음과 같은 작업을 해야 합니다.

IAR EWARM이 설치된 폴더내의 ​arm\src\lib\dlmalloc.c 파​일을 프로젝트에 추가합니다.

NO_MALLINFO 를 0으로 선언합니다. 

NO_MALLOC_STATS 를 0으로 선언합니다.

* 첨부된 예제 프로젝트를 다운로드 하여 참고 하실 수 있습니다.

 

 

 

__iar_dlmalloc_stats

__iar_dlmalloc_stats() 함수는 전체 힙 크기와 사용된 힙 크기를 표준 출력(stdout)으로 출력합니다.

 

220f5d5b3a25fe3f18fc6ae70530e7a2_1491404545_3351.png


 

 

 

 __iar_dlmallinfo

__iar_dlmallinfo() 함수는 힙의 크기와 사용 정보를 확인할 수 있는 구조체를 리턴합니다.

220f5d5b3a25fe3f18fc6ae70530e7a2_1491404553_5811.png

 

 

mallinfo의 구조체는 아래와 같은 정보를 담고 있습니다.

 #if !NO_MALLINFO

/*

  mallinfo()

  Returns (by copy) a struct containing various summary statistics:

 

  arena:     current total non-mmapped bytes allocated from system

  ordblks:   the number of free chunks

  smblks:    always zero.

  hblks:     current number of mmapped regions

  hblkhd:    total bytes held in mmapped regions

  usmblks:   the maximum total allocated space. This will be greater

                than current total if trimming has occurred.

  fsmblks:   always zero

  uordblks:  current total allocated space (normal or mmapped)

  fordblks:  total free space

  keepcost:  the maximum number of bytes that could ideally be released

               back to system via malloc_trim. ("ideally" means that

               it ignores page restrictions etc.)

 

  Because these fields are ints, but internal bookkeeping may

  be kept as longs, the reported values may wrap around zero and

  thus be inaccurate.

*/

struct mallinfo dlmallinfo(void);

#endif /* NO_MALLINFO */

이와 같이 IAR에서 제공하는 라이브러리를 사용하여 프로그램에서 사용되는 힙의 크기를 예측하여야 합니다.

예측된 크기에 약 25%~100%의 margin을 추가로 설정하여 사용하시기 바랍니다.

 

 

 

힙 크기 변경

사용되는 힙의 크기는 아래와 같이 컴파일러에서 설정할 수 있습니다. 

힙의 크기는 프로젝트 옵션의 Linker항목에서 설정합니다.

Linker의 Config에서 Edit를 눌러 링커 설정을 변경합니다. 

Stack/Heap Sizes탭에서 HEAP의 값을 변경합니다.  

220f5d5b3a25fe3f18fc6ae70530e7a2_1491404565_5595.png
 

 

할당된 heap의 크기는 map파일에서 확인할 수 있습니다.

220f5d5b3a25fe3f18fc6ae70530e7a2_1491404572_3404.png
 


Comments

Category
Facebook Twitter GooglePlus KakaoStory NaverBand