본문 바로가기

COMPUTER/기타

leaks로 Memory leak 체크하기

42 서울 과제를 하면서 가장 많이 하는 건 릭체크와, 릭 막는 일.. 이라고 해도 과언이 아닐정도로 동적할당이 필요한 일을 하는 순간부터 아주아주 많은 릭이 발생한다. 흑흑. 그래서 오늘은 Memory leak과, 발생하는 이유들, 그리고 해제가 제대로 되었는지를 확인하는 방법들을 작성해 보려고 한다. 42 에서는 C languge를 기반으로 과제를 진행하기 때문에, 대부분의 설명은 모두 C 기반으로 이루어 질 예정.

 

# Memory leak

Memory leak이란 메모리 공간에 누수가 발생했음을 의미한다. C로 프로그래밍을 하다보면, 우리는 동적할당이란걸 하게 되는데 간단하게 설명하자면 동적할당은 메모리에 내가 이만큼의 공간을 사용할 거야! 하고 메모리 공간을 할당 받는 것 같은거다. 데이터를 저장함에 있어서 언제 들어올 지 모르는 데이터를 위해 매번 1000씩 공간을 할당해 두는 것은 비효율적이니, 필요한 만큼의 메모리 공간을 가변적으로(?) 할당 받는데 이용한다. 그런데 이런 데이터들은 마치 호텔 체크인 하는 것과 같아서, free라는 명령어를 통해 메모리 사용이 끝났다는 것을 말해주지 않으면 메모리 영역에서는 그 공간이 계속 사용중이라고 여기게 된다. 결국 메모리의 힙 영역의 데이터가, 실제로 사용되고 있지 않는데 사용되고 있다고 여겨져서 그만큼의 공간을 사용할 수 없게 되는 데, 그런 경우를 memory leak이라고 한다.

 

## Memory leak은 언제 발생할까?

Memory leak은 다양하게 발생한다. 단순하게 free를 안해서, 동적할당이 두번 되어서, 동적할당을 하고 할당된 주소값을 반환받지 않아서 등등... ( C에서 사용하는 경우 malloc에서 할당 된 주소값을 반환한다. 기억하지 않으면 호텔 예약해놓고, 어느호텔인지 기억 못하는 것과 같다.) 통틀어서 할당된 메모리를 해제해주지 않으면 leak은 항상 일어난다. 아래는 흔히 발생하는 memory leak들을 코드로 작성해보았다. 실제로 malloc만 사용할 때에는 잘 발생하지 않지만, 여러 함수를 이용해서 코드를 짤 때에는 함수 자체에 할당 기능(?)이 있을 수 있어서, 함수를 잘 모르고 쓰면 종종 발생하는 leak들이다.

#include <stdio.h>
#include <stdlib.h>

// 할당을 하고 프리하지 않은경우
int		leak1(void)
{
	char	*str = (char*)malloc(sizeof(char) * 10);
	if (!str)
		return (0);
	return (0);
}

// 할당을 하고, 같은 곳에 또다시 할당한 경우
int		leak2(void)
{
	char	*str = (char*)malloc(sizeof(char) * 10);
	if (!str)
		return (0);
	str = (char*)malloc(sizeof(char) * 10);
	free(str);
	return (0);
}

int		main(void)
{
	leak1();
	leak2();
}

 

# Memory Leak을 체크하는 방법

이제 본론으로 들어와서, Memory leak을 체크하는 방법에 대해 알아보자. 메모리 릭을 체크하는 방법은 여러가지가 있는데, 그중에서 leaks, valgrind, gcc sanitizer option 에 대해서 작성해 보려고 한다.

 

## leaks

man leaks

가장 간단한 방법(?)은 그냥 BSD커맨드를 이용하는 거다. Unix 환경에서는 해당 커맨드를 이용할 수 있는데, leaks 를 이용하면 프로세스의 메모리에서 leak을 찾아준다. 사용하는 방법은 프로그램(ex. a.out)을 실행시켜 놓고 leaks [실행파일 명] 을 터미널에 입력하면 된다. 해당 명령어는 실행중인 프로세스에 대해서 leak을 찾아내는 것이기 때문에, 주로 main에 while(1)을 이용해서 프로그램을 계속 실행되게끔 한 후 이용한다. 꼭 무한루프가 아니더라도 주기적으로 프로그램을 실행 시키는 방법도 있다.

leaks a.out 을 실행한 결과 (좌 : memory leak이 발생한 경우, 우 : 발생하지 않은 경우)

해당 파일은 위에 릭이 발생하는 여러가지 경우의 코드를 가지고 실행시킨 결과이다. leaks을 실행하게 되면, 현재 어느만큼의 메모리 누수가 발생하고 있는지에 대해 알려준다. 리스트로 결과를 보고싶다면 -list 옵션을 넣거나, 위해 실행 일자 등 없이 결과만 보고싶다면 -quiet 옵션을 사용할 수도 있다. 더 자세한 설명과 다양한 옵션들은 man leaks 을 참고하면 된다.

 

# 릭체크를 하는 다른 방법 (gcc option, valgrind ...)

릭 체크를 하는 방법은 leaks 외에도 다른 방법들이 더 있는데, 운영체제, 운영체제 버전, 컴파일러 버전 등에 따라서 지원 여부가 달라지니 해당 부분에 대한 체크가 필요하다.

## gcc -fsanitize=leak

참고 링크

* gcc options [gcc.gnu.org/onlinedocs/gcc/Instrumentation-Options.html]

* gcc AddressSanitize [github.com/google/sanitizers/wiki/AddressSanitizerLeakSanitizer]

 

두번째 방법은 컴파일러 옵션을 이용하는 방법이다. 해당 옵션은  Linux, Darwin (OS X and iOS Simulator), FreeBSD, Android OS를 지원한다.

 

## Valgrind

참고링크

* valgrind [valgrind.org/]

 

마지막은 valgrind 라는 릭체크 툴을 이용하는 것. 외부 프레임워크를 이용하는 것이라서 설치과정이 필요하다. Mac 환경이라면 homebrew를, Linux 환경이라면 apt 를 이용해 설치해주면 된다. Linux는 apt intall valgrind 를 사용하면 설치가 되고,  Mac의 경우에는 단순하게 brew install valgrind를 하게되면, 에러가 나는 것을 볼 수 있을 텐데 다음 블로그를 참고하여 설치하면 된다. (* How to Install Vargrind on Mac [www.gungorbudak.com/blog/2018/04/28/how-to-install-valgrind-on-macos-high-sierra/] )

 

내 경우에는 다운로드를 하다가 버전 문제로 실패했다. valgrind는 다음 운영체제에서 사용이 가능한데, Darwin 10.x, 11.x, 12.x, 13.x, 14.x, 15.x, 16.x and 17.x (Mac OS X 10.6/7/8/9/10/11 and macOS 10.12/13) 현재 최신 운영체제인 카탈리나는 10.15 버전이므로 사용할 수 없다....저런...

 

'COMPUTER > 기타' 카테고리의 다른 글

Static Variable 이 무엇일까?  (0) 2020.08.30