C언어 메모리 해제 관련 질문 좀 드립니다.

어쩌라구의 이미지

먼저 제가 테스트 하던 소스 코드를 보시면 아래와 같습니다.

  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이 일어나 문제가 발생하는거
같기도 하고 대체 감을 못 잡겠네요....;;;

mg2000의 이미지

유닉스마다 메모리 관리 방식이 달라서, 바로 바로 해제해 주는 OS도 있고, 당장 해제하지 않는 OS도 있습니다.

어쩌라구의 이미지

O.S는 Ubuntu Linux 2.6.28-15-generic 입니다..

mg2000의 이미지

해외 포럼을 보니, top말고 htop이라는 것을 이용하면, 실제 사용중인 메모리와 그냥 버퍼로 잡고 있는 메모리를 보여준다고 하네요.

sudo apt-get install htop
htop

요걸로 한번 확인해 보시면 어떨까요?

http://ubuntuforums.org/showthread.php?t=853304

어쩌라구의 이미지

댓글 감사합니다. 하지만 htop으로 확인해봐도 top과 같은 결과가 나오네요.;

mg2000의 이미지

mem2 해제 안해서 그런건 아니겠죠? (mem2의 free부분은 주석으로 되어 있는데, new로 할당했으니, delete로 해제해야 할테고요.)

어쩌라구의 이미지

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 입니다.

haze11의 이미지

new를 보니 c++ ? =.=

jick의 이미지

free는 메모리를 런타임 라이브러리(그러니까 glibc)에 반환해서, 다음번에 malloc할 때 가져다 쓸 수 있게 하는 역할을 합니다. 이 메모리를 다시 OS에 반환할지 말지는 glibc 맘대로 결정하는데,

일반적으로 잘 반환하지 않습니다.

왜냐하면 OS를 불러서 메모리를 요청하거나 반환하는 것은 system call이 들어가서 비용이 매우 비싸기 때문입니다. 그러므로 일반적인 경우라면 라이브러리가 free한 메모리를 그냥 들고 있다가 다음번 malloc이 들어오면 적당히 잘라서 주는 게 훨씬 싸게 먹힙니다.

이게 정말로 크리티컬한 문제가 되는 경우라면 (메모리가 모자라서 반환했는데 수십 메가를 glibc가 그냥 들고 있다든지...) 아예 malloc/free 대신 mmap/munmap을 직접 부르는 독자노선으로 가는 길이 있는데... 워낙 신경쓸 게 많아지기 때문에, 무슨 상용 웹서버나 DB 정도 짜는 게 아니면 별로 추천해드리고 싶지는 않습니다.

* 추가: 혹시 이 문제일지도 모르겠는데... new로 잡은 메모리는 반드시 delete로 반환해야 합니다. 위의 코드와 같은 경우 new char[...]로 잡았으니 delete[]로 반환해야 합니다.

pastime의 이미지

glibc는 malloc으로 할당한 메모리를 일정한 크기가 되기 전까진 시스템에 반환하지 않고 유지합니다.
이 때 기준이 되는 크기는 MALLOC_TOP_PAD_ 및 MALLOC_TRIM_THRESHOLD_ 변수로 지정할 수 있는데
기본값은 128K로 지정되어 있습니다.

아래의 글도 살펴보시면 도움이 될 듯... ^^;;
http://studyfoss.egloos.com/5209389

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.