C언어 메모리 해제 관련 질문 좀 드립니다.
글쓴이: 어쩌라구 / 작성시간: 목, 2010/02/18 - 9:21오전
먼저 제가 테스트 하던 소스 코드를 보시면 아래와 같습니다.
1 #include <unistd.h> 2 #include <stdio.h> 3 #include <stdlib.h> 4 #include <string.h> 5 #include <malloc.h> 6 7 #define MAX_MEM_SIZE 500 8 // #define MEM_COUNT 5000 9 #define MEM_COUNT 4000 10 11 int main() 12 { 13 char *mem[MEM_COUNT]; 14 15 printf("Starting malloc... %d & %d = %dm\n", MAX_MEM_SIZE*1024*1024 / MEM_COUNT, MEM_COUNT, MAX_MEM_SIZE); 16 for (unsigned int i=0; i<MEM_COUNT; i++) { 17 mem[i] = (char *)malloc(MAX_MEM_SIZE*1024*1024 / MEM_COUNT); 18 memset(mem[i], 0, MAX_MEM_SIZE*1024*1024 / MEM_COUNT); 19 } 20 printf("Done.\n"); 21 22 char *mem2 = new char[MAX_MEM_SIZE*1024*1024 / MEM_COUNT]; 23 sleep(10); 24 25 26 printf("Starting free...\n"); 27 for (unsigned int i=0; i<MEM_COUNT; i++) { 28 free( mem[i] ); 29 mem[i] = NULL; 30 } 31 32 printf("free(mem) Done.\n"); 33 sleep(15); 34 35 // free(mem2); 36 // printf("free(mem2) Done.\n"); 37 // sleep(15); 38 }
문제는 상단의 MEM_COUNT를 4000 으로 하고 실행을 시켜 TOP으로 해당 프로세스를 잡아보면 28라인의
free(mem[i]) 이후에 메모리가 반환되는걸 알 수가 있습니다. 하지만 MEM_COUNT 5000으로 실행시에는 28라인의
free(mem[i]) 이후에도 메모리가 반환이 되지 않습니다. 128K 전후로 Memory Paging이 일어나 문제가 발생하는거
같기도 하고 대체 감을 못 잡겠네요....;;;
Forums:
어디서 테스트 하시는건지?
유닉스마다 메모리 관리 방식이 달라서, 바로 바로 해제해 주는 OS도 있고, 당장 해제하지 않는 OS도 있습니다.
O.S는 Ubuntu Linux
O.S는 Ubuntu Linux 2.6.28-15-generic 입니다..
우분투는 많이 안써봐서 모르겠지만...
해외 포럼을 보니, top말고 htop이라는 것을 이용하면, 실제 사용중인 메모리와 그냥 버퍼로 잡고 있는 메모리를 보여준다고 하네요.
sudo apt-get install htop
htop
요걸로 한번 확인해 보시면 어떨까요?
http://ubuntuforums.org/showthread.php?t=853304
댓글 감사합니다.
댓글 감사합니다. 하지만 htop으로 확인해봐도 top과 같은 결과가 나오네요.;
관계 없는 얘기일지도 모르지만...
mem2 해제 안해서 그런건 아니겠죠? (mem2의 free부분은 주석으로 되어 있는데, new로 할당했으니, delete로 해제해야 할테고요.)
mem2 해제와 관련이
mem2 해제와 관련이 있는건지...저도 확신히 들지 않는게
MEM_COUNT 4000으로 실행 시에는 28라인 free(mem[i])
이후에 TOP에서 남은 메모리가 그만큼 더 커지는데,
문제는 MEM_COUNT 5000으로 할때 28 라인 free() 에서는
메모리가 반환되지 않는거였어요
혹시나 해서 35~37의 주석 라인을 넣어서 실행할때는
35라인의 free(mem2) 이후 메모리가 모두 반환이
되는게 확인 되었습니다.
아무래도 4000과 5000으로 실행 시에 mem[i] 마다
할당되는 메모리 크기와 관련이 있는 문제인거 같습니다.
참고로 MEM_COUNT 때 잡히는 메모리는
4000일때는 mem[i] 당 131072 byte(128Kbyte) 이고
5000일때는 mem[i] 당 104857 byte 입니다.
new를 보니 c++ ? =.=
new를 보니 c++ ? =.=
정상입니다
free는 메모리를 런타임 라이브러리(그러니까 glibc)에 반환해서, 다음번에 malloc할 때 가져다 쓸 수 있게 하는 역할을 합니다. 이 메모리를 다시 OS에 반환할지 말지는 glibc 맘대로 결정하는데,
일반적으로 잘 반환하지 않습니다.
왜냐하면 OS를 불러서 메모리를 요청하거나 반환하는 것은 system call이 들어가서 비용이 매우 비싸기 때문입니다. 그러므로 일반적인 경우라면 라이브러리가 free한 메모리를 그냥 들고 있다가 다음번 malloc이 들어오면 적당히 잘라서 주는 게 훨씬 싸게 먹힙니다.
이게 정말로 크리티컬한 문제가 되는 경우라면 (메모리가 모자라서 반환했는데 수십 메가를 glibc가 그냥 들고 있다든지...) 아예 malloc/free 대신 mmap/munmap을 직접 부르는 독자노선으로 가는 길이 있는데... 워낙 신경쓸 게 많아지기 때문에, 무슨 상용 웹서버나 DB 정도 짜는 게 아니면 별로 추천해드리고 싶지는 않습니다.
* 추가: 혹시 이 문제일지도 모르겠는데... new로 잡은 메모리는 반드시 delete로 반환해야 합니다. 위의 코드와 같은 경우 new char[...]로 잡았으니 delete[]로 반환해야 합니다.
MALLOC_TOP_PAD_ 및 MALLOC_TRIM_THRESHOLD_
glibc는 malloc으로 할당한 메모리를 일정한 크기가 되기 전까진 시스템에 반환하지 않고 유지합니다.
이 때 기준이 되는 크기는 MALLOC_TOP_PAD_ 및 MALLOC_TRIM_THRESHOLD_ 변수로 지정할 수 있는데
기본값은 128K로 지정되어 있습니다.
아래의 글도 살펴보시면 도움이 될 듯... ^^;;
http://studyfoss.egloos.com/5209389
댓글 달기