아두이노 남아있는 메모리 (메모리 사용량) 확인하기 - 메모리 공포에서 벗어나자.
아두이노 에서 사용하는 마이크로 컨트롤러는 작은 양의 RAM 공간을 갖고 있습니다. 아두이노 우노 에서 사용하는 ATmega328 계열은 고작2Kbyte 의 공간을 갖고 있으며 기본적으로 200에서 300byte 정도의 메모리가 소비되는 것을 볼 수 있었습니다.
스케치 코드를 짜면서 무분별한 변수 선언이나 지나친 메모리 할당은 아두이노 스케치가 오동작 할 수 있는 상황을 야기시킬 수 있기 때문에 코딩중 고심하게 만드는 부분중에 하나입니다. 심지어 메모리 누수(Memory leak) 버그가 발생하면 코딱지 만한 메모리 공간은 쓰레기로 가득 찰 것입니다.
<Atmega 의 메모리. 출처 : avr-libc >
다행히도 아두이노에 남아있는 메모리 사용량을 실시간으로 체크할 수 있는 방법이 존재합니다. 그리고 그것을 라이브러리로 쓰기 편하게 만들어 주신 분도 있습니다. 우선 마음속으로 라이브러리 제작자분에게 '감사합니다' 를 한 번 외친후에 아래 링크에서 라이브러리 파일을 다운받아 아두이노 툴에 추가시켜줍니다.
https://github.com/maniacbug/MemoryFree
사용방법은 무지 간단한데, 라이브러리 include (#include <MemoryFree.h>) 한 다음으로 loop() 내에서 freeMemory() 호출 하면 그 결과값을 통하여 현재 남아있는 메모리 사용량을 Kbyte 단위로 알 수 있습니다.
저는 라이브러리에 포함된 예제 코드에 아주 간단한 리스트를 만들고 노드를 계속 추가하면서 메모리 사용량을 살펴보는 코드를 작성해 보았습니다. 만약 노드를 추가하다가 남아있는 메모리가 얼마 없다면 리스트를 전부 제거시켜줍니다.
MemoryFreeTest.ino::
#include <MemoryFree.h> void setup()
{ Serial.begin(115200); } class Node
{ public : // 다음 경로. Node* next; // 메모리 사용을 지켜보기 위하여 100byte 의 배열 생성. byte buf[100]; }; // 시작 경로. 이 것은 제거되지 않는다. Node* beginNode = new Node(); Node* topNode = beginNode; void loop()
{ Serial.print("freeMemory()="); Serial.println(freeMemory()); delay(1000); /* 남아있는 메모리가 500byte 이상이면 노드를 생성하여 추가.*/ if(freeMemory() > 500)
{ addNode(); }
else
{ /*모든 노드를 제거하여 메모리 공간을 확보한다.*/ clearNode(); } } void addNode()
{ topNode->next = new Node(); topNode = topNode->next; } void clearNode()
{ Node* itor = beginNode->next; while(itor)
{ Node* next = itor->next; delete itor; itor = next; } topNode = beginNode; Serial.println("Clear!"); }
결과::
좀 더 테스트 하면서 정확성을 확인해 봐야겠지만, 일단은 위와 같이 잘 동작합니다.
만약 메모리 릭이 발생했을때의 상황도 재현해 보았습니다.
방법은 위 코드에서 Node 클래스의 buf 배열의 사이즈를 500으로 늘려서 한 번에 504 바이트씩 할당 하도록 하고, clear 하는 부분은 제거하였습니다.
그 결과는 아래와 같습니다.
마치 수치 상으로는 메모리 공간이 없으면 더이상 할당이 안 되는 것처럼 보이지만, 사실 내부적으로 무슨 일이 일어나고 있는지도 모릅니다. 저도 아직까지는 정확히는 확인할 길이 없어서 확인을 안 했지만 혹시나 아두이노의 메모리를 실시간으로 들여다 볼 수 있는 방법이 있으면 이 포스팅을 업데이트 하겠습니다.