메모리 누수 - WindyHana's Solanara

목차

개요

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

  1. 예제1

    leak.c
    #include <unistd.h>
    #include <stdlib.h>
    void main () {
    	void * m;
    	m = malloc(10);
    	m = malloc(30); // 위에서 할당한 10바이트의 메모리를 해제할 수 없다.
    	m = malloc(50); // 위에서 할당한 30바이트의 메모리를 해제할 수 없다.
    	sleep(30);
    }
    
    root@wl # cc -g -o leak 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. 누수 감지 원리

    leak2.c
    #include <stdio.h>
    #include <unistd.h>
    #include <stdlib.h>
    void main () {
    	printf("PID: %d\n", getpid());
    	void * m = malloc(10 * 1024);
    	printf("%s\n", "10킬로바이트할당");
    	long a = (long) m / 4;
    	long b = (long) m % 4;
    	while (1==1) {
    		m = malloc(200 * 1024);
    		printf("%s\n", "200킬로바이트할당");
    		sleep(20); // STEP 1
    		void * m2 = (void *) (a * 4 + b);
    		free(m2);
    		printf("%s\n", "10킬로바이트해제");
    		sleep(20); // STEP 2
    		free(m);
    		printf("%s\n", "200킬로바이트해제");
    		sleep(20); // STEP 3
    		break;
    	}
    }
    
    root@wl # UMEM_DEBUG=default UMEM_LOGGING=transaction LD_PRELOAD=libumem.so.1 ./leak2
    PID: 2631
    10킬로바이트할당
    200킬로바이트할당
    10킬로바이트해제
    200킬로바이트해제
    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를 이용한 메모리 누수 감지

leak3.c
#include <unistd.h>
#include <stdlib.h>
void main () {
	void * m;
	m = malloc(10);
	m = malloc(50);
	free(m);
}
mfs.d
#!/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 leak3.c
root@wl ~ # dtrace -s mfs.d -c ./leak3 libc
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를 이용해 메모리 누수를 확인하기 위해서는 dbx 커맨드에서 [check -leaks] 명령을 내린 후 실행 해보면 된다.
root@wl ~ # cc -o leak3 -g 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 ~ #

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

Twitter RSS IconTexto 올바른 XHTML 1.0 Transitional 입니다 올바른 CSS입니다!