메모리 누수 - 윈디하나의 솔라나라

목차

개요

libumem을 이용한 메모리 누수 감지

  1. 예제1

    memoryleak_leak.c
    (152 바이트)
    #include <unistd.h>
    #include <stdlib.h>
    
    int main(int argc, char *argv[]) {
    	void * m;
    	m = malloc(10);
    	m = malloc(30);
    	m = malloc(50);
    	sleep(10);
    }
    
    root@wl ~ # cc -g -o leak memoryleak_leak.c 1) 
    root@wl ~ # UMEM_DEBUG=default UMEM_LOGGING=transaction LD_PRELOAD=libumem.so.1 ./leak & 2) 
    [1] 2171
    root@wl ~ # gcore 2171 3) 
    gcore: core.2171 dumped
    root@wl ~ # mdb core.2171 4) 
    Loading modules: [ libumem.so.1 libc.so.1 ld.so.1 ]
    > ::umem_status
    > ::umem_log
    > ::umalog
    ...
    > ::findleaks
    CACHE     LEAKED   BUFCTL CALLER
    080798d0       1 0808ae30 main+0xf
    08079c50       1 0808eaf8 main+0x1e
    ----------------------------------------------------------------------
       Total       2 buffers, 64 bytes
    Ctrl+D
    root@wl ~ # 
    
    1) 샘플 프로그램을 만들고 컴파일한다.
    2) LD_PRELOAD를 이용해 컴파일한 프로그램을 실행시킨다.
    3) 프로그램의 덤프를 얻는다.
    4) mdb로 분석한다. 2곳에서 메모리 누수가 발생한것을 알 수 있다.
  2. 누수 감지 원리

    memoryleak_leak2.c
    (606 바이트)
    #include <stdio.h>
    #include <unistd.h>
    #include <stdlib.h>
    
    int main(int argc, char *argv[]) {
        printf("PID: %d\n", getpid());
        void * m = malloc(10 * 1024);
        printf("%s\n", "Alloc 10KB");
        long a = (long) m / 4;
        long b = (long) m % 4;
        while (1 == 1) {
            m = malloc(200 * 1024);
            printf("%s\n", "Alloc 200KB");
            sleep(20); // STEP 1
            void * m2 = (void *) (a * 4 + b);
            free(m2);
            printf("%s\n", "Free 10KB");
            sleep(20); // STEP 2
            free(m);
            printf("%s\n", "Free 200KB");
            sleep(20); // STEP 3
            break;
        }
    }
    
    root@wl ~ # UMEM_DEBUG=default UMEM_LOGGING=transaction LD_PRELOAD=libumem.so.1 ./leak2
    PID: 2631
    Alloc 10KB
    Alloc 200KB
    Free 10KB
    Free 200KB
    root@wl ~ #
    
    root@wl ~ # mdb core.2631.step1 STEP 1
    Loading modules: [ libumem.so.1 libc.so.1 ld.so.1 ]
    > ::findleaks
    CACHE     LEAKED   BUFCTL CALLER
    08082a90       1 0808af08 main+0x25
    ----------------------------------------------------------------------
       Total       1 buffer, 12288 bytes
    >
    root@wl # mdb core.2631.step2 STEP 2
    Loading modules: [ libumem.so.1 libc.so.1 ld.so.1 ]
    > ::findleaks
    CACHE     LEAKED   BUFCTL CALLER
    ----------------------------------------------------------------------
       Total       0 buffers, 0 bytes
    >
    root@wl # mdb core.2631.step3 STEP 3
    Loading modules: [ libumem.so.1 libc.so.1 ld.so.1 ]
    > ::findleaks
    CACHE     LEAKED   BUFCTL CALLER
    ----------------------------------------------------------------------
       Total       0 buffers, 0 bytes
    >
    root@wl ~ #
    
    

DTrace를 이용한 메모리 누수 감지

memoryleak_leak3.c
(145 바이트)
#include <unistd.h>
#include <stdlib.h>

int main(int argc, char *argv[]) {
    void * m;
    m = malloc(10);
    m = malloc(50);
    free(m);
}
memoryleak_mfs.d
(210 바이트)
#!/usr/sbin/dtrace -s
pid$target:$1:malloc:entry
{
    ustack();
}
pid$target:$1:malloc:return
{
    printf("%s: %x\n", probefunc, arg1);
}
pid$target:$1:free:entry
{
    printf("%s: %x\n", probefunc, arg0);
}
root@wl ~ # cc -o leak3 memoryleak_leak3.c
root@wl ~ # dtrace -s mfs.d -c ./leak3
dtrace: script 'mfs.d' matched 3 probes
dtrace: pid 7205 has exited
CPU     ID                    FUNCTION:NAME
  0  57771                     malloc:entry
              libc.so.1`malloc
              leak3`main+0xf
              leak3`_start+0x7d

  0  57772                    malloc:return malloc: 80608a8 1)

  0  57771                     malloc:entry
              libc.so.1`malloc
              leak3`main+0x1e
              leak3`_start+0x7d

  0  57772                    malloc:return malloc: 8060ea8 2)

  0  57773                       free:entry free: 8060ea8 3)
1) 80608a8 주소에 메모리 할당
2) 8060ea8 주소에 메모리 할당
3) 8060ea8 주소에 메모리 해제

dbx를 이용한 메모리 누수 감지

dbx(1)를 이용해 메모리 누수를 확인하기 위해서는 dbx 커맨드에서 check -leaks 명령을 내린 후 실행 해보면 된다. dbx는 Solaris Studio 에 번들되어있다.
root@wl ~ # cc -o leak3 -g memoryleak_leak3.c
root@wl ~ # dbx leak3
For information about new features see `help changes'
To remove this message, put `dbxenv suppress_startup_message 7.7' in your .dbxrc
Reading leak3
Reading ld.so.1
Reading libc.so.1
(dbx) help check
...
(dbx) check -leaks
leaks checking - ON
(dbx) run
Running: leak3
(process id 7796)
Reading rtcapihook.so
Reading libdl.so.1
Reading rtcaudit.so
Reading libmapmalloc.so.1
Reading libgen.so.1
Reading libm.so.2
Reading rtcboot.so
Reading librtc.so
RTC: Enabling Error Checking...
RTC: Running program...
Checking for memory leaks...

Actual leaks report    (actual leaks:            1  total size:         10 bytes)

  Total     Num of  Leaked     Allocation call stack
  Size      Blocks  Block
                    Address
==========  ====== =========== =======================================
        10       1  0x80608b0  main

Possible leaks report  (possible leaks:          0  total size:          0 bytes)

execution completed, exit code is 0
(dbx) exit
root@wl ~ #

watchmalloc

Use After Free

Valgrind

root@wll ~ # gcc -o leak -g memoryleak_leak.c
root@wll ~ # valgrind --leak-check=full ./leak
==4123== Memcheck, a memory error detector
==4123== Copyright (C) 2002-2012, and GNU GPL#39;d, by Julian Seward et al.
==4123== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==4123== Command: ./leak
==4123==
==4123==
==4123== HEAP SUMMARY:
==4123==     in use at exit: 90 bytes in 3 blocks
==4123==   total heap usage: 3 allocs, 0 frees, 90 bytes allocated
==4123==
==4123== 10 bytes in 1 blocks are definitely lost in loss record 1 of 3
==4123==    at 0x4A069EE: malloc (vg_replace_malloc.c:270)
==4123==    by 0x40051C: main (memoryleak_leak.c:6)
==4123==
==4123== 30 bytes in 1 blocks are definitely lost in loss record 2 of 3
==4123==    at 0x4A069EE: malloc (vg_replace_malloc.c:270)
==4123==    by 0x40052A: main (memoryleak_leak.c:7)
==4123==
==4123== 50 bytes in 1 blocks are definitely lost in loss record 3 of 3
==4123==    at 0x4A069EE: malloc (vg_replace_malloc.c:270)
==4123==    by 0x400538: main (memoryleak_leak.c:8)
==4123==
==4123== LEAK SUMMARY:
==4123==    definitely lost: 90 bytes in 3 blocks
==4123==    indirectly lost: 0 bytes in 0 blocks
==4123==      possibly lost: 0 bytes in 0 blocks
==4123==    still reachable: 0 bytes in 0 blocks
==4123==         suppressed: 0 bytes in 0 blocks
==4123==
==4123== For counts of detected and suppressed errors, rerun with: -v
==4123== ERROR SUMMARY: 3 errors from 3 contexts (suppressed: 6 from 6)

상용 메모리 누수 감지 소프트웨어

RSS ATOM XHTML 5 CSS3