GW LABS

리눅스 Strace & Valgrind 디버깅 기법 본문

Infrastructure

리눅스 Strace & Valgrind 디버깅 기법

GeonWoo Kim 2019. 4. 14. 12:56

누수를 발생시킨 본인은 조커가 되고,  팀원들은 정신줄을 놓는다!

 

WAS에서 작동시켜야 하는 데몬이나 스케줄러 같은 프로그램들이 메모리 누수를 발생시키면 정말 골치 아파진다. 프로그래머가 가비지 컬렉터만 믿고 있었면 안 된다는 사실을 뼈저리게 느끼고 있다. 최근 php로 작성한 스케줄러가 미약한 메모리 누수를 발생시키고 있어 다양한 디버깅 기법을 찾아봤다. 리눅스 환경이라면 시스템 콜을 추적할 수 있는 Strace와 프로그램의 메모리 사용을 볼 수 있는 Valgrind를 통해 프로그램을 깊이 들여다볼 수 있다. 좋은 디버깅 툴을 사용해서 미연에 메모리 누수를 방지하자. 

 

 


 

 

1. 메모리 누수 상황

#include <iostream>

using namespace std;

class LeakMaker
{
    private:
        const int data;
    public:
        LeakMaker(int a)
            : data(a)
        {
            cout << "생성됨" << endl;
        }

        ~LeakMaker()
        {
            cout << "삭제됨" << endl;
            delete this;
        }
};

int main()
{
    int flag;
    LeakMaker *leakMaker;
    while (true)
    {
        cin >> flag;
        if (flag == 1)
        {
            leakMaker = new LeakMaker(15);
        } else {
            break;
        }
    }
    
    return 0;
}

명백한 메모리 누수상황을 만들어봤다. LeakMaker를 동적으로 선언하고 메모리를 해제하지 않은 코드이다. 이런 코드를 Strace와 Valgrind를 통해서 프로그램이 어떻게 동작하고 있는지 살펴보자.

 

 

2. Strace

Strace는 시스템 콜과 시그널을 추적하면서 프로그램의 문제를 진단할 수 있는 디버깅 툴이다. 위의 프로그램을 실행시키고 Strace를 통해서 시스템 콜 로그를 살펴보자.

 

strace -o log_file -p <pid>

 

위의 프로그램대로 1을 몇 번 입력하고 프로그램을 종료시키면 로그파일이 생성된다. 해당 로그 파일의 로그를 살펴보면

 

   read(0, "1\n", 1024) = 2

   write(1, "\354\203\235\354\204\261\353\220\250\n", 10) = 10

   read(0, "1\n", 1024) = 2

   write(1, "\354\203\235\354\204\261\353\220\250\n", 10) = 10

   read(0, 0x5569d28cae70, 1024) = ? ERESTARTSYS (To be restarted if SA_RESTART is set)

   --- SIGINT {si_signo=SIGINT, si_code=SI_KERNEL} ---

   +++ killed by SIGINT +++

 

cin을 통해 시스템 콜인 read, write가 발생하는 것을 볼 수 있다. 위의 프로그램의 경우 strace로는 메모리 누수를 진단할 수 없었다.

 

 

3. Valgrind

Valgrind는 리눅스 환경에서 프로그램의 메모리 디버깅 툴이다. 위의 프로그램을 valgrind를 통해서 실행해보자.

 

valgrind --leak-check=yes <실행시킬 프로그램>

 

valgrind를 프로그램을 실행시킨 후 1을 한 번 입력한 후 프로그램을 종료시켰다. 그러면 valgrind가 메모리를 진단한 로그를 화면에 출력한다.

 

==9087== Memcheck, a memory error detector
==9087== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==9087== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==9087== Command: ./Leak
==9087== 
1
생성됨
2
==9087== 
==9087== HEAP SUMMARY:
==9087==     in use at exit: 4 bytes in 1 blocks
==9087==   total heap usage: 4 allocs, 3 frees, 74,756 bytes allocated
==9087== 
==9087== 4 bytes in 1 blocks are definitely lost in loss record 1 of 1
==9087==    at 0x4C3017F: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==9087==    by 0x108B88: main (in /home/gwkim/바탕화면/dev/cpp/memoryCheck/Leak)
==9087== 
==9087== LEAK SUMMARY:
==9087==    definitely lost: 4 bytes in 1 blocks
==9087==    indirectly lost: 0 bytes in 0 blocks
==9087==      possibly lost: 0 bytes in 0 blocks
==9087==    still reachable: 0 bytes in 0 blocks
==9087==         suppressed: 0 bytes in 0 blocks
==9087== 
==9087== For counts of detected and suppressed errors, rerun with: -v
==9087== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

 

LEAK SUMMARY에서 definitely lost 하나가 발견되었다. 디버깅해야 할 부분이 보인다!

 

 

 


 

 

 

Strace와 Valgrind는 강력한 리눅스 디버깅 도구이다. 더 많은 에러 상황 연습과 사용법 숙지를 통해서 치명적인 메모리 누수 문제를 해결할 수 있는 개발자가 되도록 노력하자.

 

 

 

 

 

Reference

 

https://linuxspot.tistory.com/253

 

[HowTo] 리눅스에서 Strace를 이용한 7가지 디버깅 예제

이 페이지의 원문은 The Geek Stuff에 포스팅 된 "7 Strace Examples to Debug the Execution of a Program in Linux" 입니다. strace는 프로그램의 문제 해결을 도와주는 디버깅 툴입니다. strace는 특정 프로그..

linuxspot.tistory.com

https://blog.naver.com/hermet/111117366

 

valgrind를 이용한 디버깅 (Linux Debugging)

valgrind (밸그린드) 에 대한 사용법을 간단히 정리합니다. http://valgrind.org (공식 사이트) 밸그린드는...

blog.naver.com

https://www.thegeekstuff.com/2011/11/strace-examples/

 

'Infrastructure' 카테고리의 다른 글

웹 앱 성능측정 도구, 라이트하우스  (0) 2020.04.29
WSL Native Docker  (0) 2019.11.26
Comments