지난 Post에 이어서 Ubuntu에서 Valgrind로 Memory Leak을 검사하는 방법의 활용편으로 Valgrind의 GUI Front-end로 Memory Leak을 검사하는 방법과 Callgrind를 사용하는 간단한 방법, 그리고 Eclipse 내에서 Valgrind를 사용하는 방법을 알아보도록 하겠습니다.

5. 유용한 Front-end

Valgrind를 사용해서 Terminal에서 Memory Leak을 검사하는 방법을 알아봤지만, 아무래도 좀 더 보기 편리하고 사용하기 쉬운 쪽이 생산성이 좋을 것입니다. 그래서 이번에는 Valgrind를 위한 유용한 Front-end를 소개하려 합니다.

5.1. Alleyoop Memory Checker

Alleyoop은 GTK+ 기반으로 만들어진 GUI Front-end입니다. 이 Program은 Valgrind의 Memcheck Tool의 결과를 좀 더 보기 쉽게 표현해 주고 해당 Code를 쉽게 확인할 수 있습니다.

먼저 설치를 위해서 Terminal에서 다음과 같이 입력합니다.

1
$ sudo apt-get install alleyoop

위에서 작성한 Test Program을 가지고 Alleyoop을 사용해서 Memory Leak을 검사해 봅시다. Terminal에서 다음과 같이 입력합니다. (아래의 예는 Source의 Directory가 ~/test, 실행 File이 ./test일 경우)

1
$ alleyoop -R ~/test/ ./test

-R Option을 사용하면 해당 Directory 내에서 Memory Leak이 발생한 Source Code를 찾게 됩니다. 만약 Memory Leak을 검사할 Program이 Argument(명령행 인자)를 가지고 있다면, 위의 명령에서 검사할 Program 뒤에 그대로 이어서 적으면 됩니다.

Alleyoop - Preferences

Alleyoop - Preferences

실행한 다음, 설정 -> 기본 설정에서 Memory Leak을 검사하기 위한 설정을 해야 합니다. 위의 그림과 같이 Memcheck Tab에서 Leak Check를 full로, Leak Resolution을 high로 설정하고 OK를 누릅니다.

Alleyoop - Run

Alleyoop - Run

그 다음 상단 Toolbar의 Run을 누르면 Program이 실행됩니다. Test Program이 종료된 후에는 위의 그림과 같이 Valgrind의 Memcheck Tool을 통해 얻은 정보가 아래의 Treeview에 표시됩니다.

Memory Leak이 발생한 경우에는 위의 그림과 같이 해당 Source의 일부분과 발생한 Line을 표시해 주기 때문에 쉽게 문제가 발생한 부분을 확인할 수 있습니다.

Gedit

Gedit

그리고 Memory Leak을 나타내는 Code를 Double-Click하면 문제가 발생한 부분을 쉽게 편집할 수 있도록 Gedit가 실행되면서 해당 Source에서 Memory Leak이 발생한 Line에 Cursor를 위치시켜 줍니다.

이외에도 Alleyoop을 사용하면 NCURSES(Console 화면 출력을 쉽게 다루기 위한 Library)를 사용한 Console Program도 쉽게 Memory Leak을 검사할 수 있습니다.

NCURSES를 사용한 Program의 경우, Alleyoop에서 Run을 누르면 Alleyoop을 실행한 Terminal에서 Program이 실행되며 Program이 종료되면 결과가 Alleyoop에 표시되게 됩니다.

5.2. KCachegrind

KCachegrind는 정확하게 말하면 Memory Leak을 검사하기 위한 Front-end는 아닙니다. 하지만, Program의 Performance 향상을 위해 사용되는 상당히 좋은 Tool로 Valgrind에 대해서 설명하는 이 Post에서 잠깐 다뤄보려 합니다.

KCachegrind는 Valgrind의 도구 중 하나인 Callgrind가 생성한 Profile Data를 시각화하여 보여주는 Tool입니다.

이 Program을 사용하면 AQTime 방식과 유사하게 Callgrind로 분석한 ASCII Data를 보기 편리하게 GUI를 통해 시각화하여 보여줌으로서 사용자에게 편의를 제공합니다. 또한 이 것을 통해서 각 Function 별 Cost(비용)와 호출 관계등을 알 수 있습니다.

먼저, 설치를 위해서 Terminal에서 다음과 같이 입력합니다.

1
$ sudo apt-get install kcachegrind

설치가 완료되었다면 이제 KCachegrind를 사용하기 위한 Profile Data를 얻어봅시다.

다음과 같이 Terminal에서 입력하여 Test할 Application의 Data를 얻습니다. (아래는 이전에 작성한 test Program의 예)

1
$ valgrind --tool=callgrind ./test

Callgrind도 마찬가지로 Runtime에 수행이 되기 때문에 Program 실행 시에 수행되지 않은 Function에 대한 Data를 얻지 못하는 것을 유의해야 합니다.

실행이 완료되면 Callgrind를 통해서 얻은 Data는 Console에 표시되는 것이 아니라 File(일반적인 경우 callgrind.out.*)로 저장됩니다.

Unity - KCachegrind

Unity - KCachegrind

이제 Data도 얻었으니 분석을 위해서 KCachegrind를 실행해 봅시다. Unity Dash에서 개발자 도구를 선택한 다음, KCachegrind를 Click합니다.

KCachegrind

KCachegrind

KCachegrind를 실행한 화면입니다. 일부 한글로 번역이 되어있으나 완전치는 않습니다.

분석한 Data를 Load하기 위해서 위의 그림과 같이 Toolbar의 열기를 누릅니다.

Select Callgrind Profile Data

Select Callgrind Profile Data

Dialog에서 Callgrind Data가 생성된 Directory로 이동한 다음 Data File을 선택하고 열기를 누릅니다.

만약 Data의 이름을 다른 것으로 변경했다면 아래의 Filter에서 Callgrind Profile Data 대신 All Files를 선택하여 모든 File이 List에 표시되도록 변경한 후 선택하면 됩니다.

KCachegrind - Callee Map and Call Graph

KCachegrind - Callee Map and Call Graph

Data를 제대로 Load했다면 위의 그림과 같이 표시될 것입니다.

분석을 위해서 간단하게 설명하면, 왼쪽 위의 최고비용 호출 스택은 Program 수행 시에 Cost가 가장 많이 발생한 Function의 순서대로 List에 표시합니다.
(Ir은 CPU에서 계산을 위해 Memory에서 Instruction을 가져오는 것을 나타내는 Instruction Fetch의 Cost(%)를, 호출은 호출 횟수를 나타냅니다.)

그리고 왼쪽 아래의 균일한 프로파일은 Runtime에 수행된 거의 모든 Function(Cost가 너무 낮은 것은 제외됨)의 Cost(%)와 호출 횟수를 표시합니다.
(포함은 각 Function 내에서 호출된 다른 Function의 Cost(%)까지를 포함한 값입니다. 그리고 Self는 호출된 다른 Function을 제외한 Function 자체의 Cost(%)를 나타내며, 호출됨은 해당 Function이 호출된 횟수를 나타냅니다.)

이 외에도, 오른쪽 상단과 하단에서는 균일한 프로파일에서 선택한 Function에 대하여 다음과 같은 정보를 제공합니다.

  • Callers: 해당 Function을 호출한 호출자를 List로 표시합니다.
  • All Callers: 호출자 뿐만 아니라 호출자를 호출한 호출자까지 포함한 List입니다.(Recursive)
  • Callee Map: Function 내부에서 호출한 다른 Function의 Cost값을 가지고 Visual한 Map을 표시합니다.
  • Source Code: Function의 Source가 존재할 경우, 해당 Function의 Code를 표시하며 각 Line 별로 Cost를 표시합니다. Source가 다른 곳에 위치할 경우, 설정 -> KCachegrind 설정 -> Annotations Tab에서 Source Directory를 추가할 수 있습니다.
  • Callee: Function 내부에서 호출한 다른 Function의 List입니다.
  • Call Graph: 해당 Function과 호출자와 호출한 다른 Function간의 호출 관계도를 표시합니다.
  • All Callees: Function 내부에서 호출한 다른 Function에서 또 다른 Function을 호출한 것까지 List로 표시합니다. (Recursive)
  • Caller Map: 호출자의 Cost값을 가지고 Visual한 Map으로 표시합니다.

KCachegrind로 얻은 위와 같은 정보를 통해서 Cost가 많이 발생하거나 호출 빈도가 높은 Function에 대해서 최적화를 수행하거나 설계 구조를 변경함으로서 Application의 Performance 향상을 꾀할 수 있을 것입니다.

KCachegrind의 자세한 기능및 분석 방법을 알고 싶다면 KCachegrind의 Documentation을 참고하기 바랍니다.

6. Eclipse CDT와 함께 사용하기

Eclipse CDT를 사용하여 개발하는 C/C++ Project에서도 IDE와 통합하여 쉽게 Valgrind로 Memory Leak을 검사할 수 있습니다.

Eclipse Classic 3.7.1 Indigo의 Linux version(또는 Eclipse IDE for C/C++ Linux Developers 1.4.1)을 통해 사용법을 간단하게 설명해 보도록 하겠습니다.

만약 Eclipse가 System에 설치되어 있지 않다면, Ubuntu에서 Eclipse CDT를 사용하여 Autotools Project 만들기 (Part 1)을 참고하여 설치하기 바랍니다.

Install Valgrind Tools Integration

Install Valgrind Tools Integration

Eclipse Classic에서 CDT를 설치한 경우라면 Valgrind를 사용하기 위한 Plugin을 설치해야 합니다. (Eclipse IDE for C/C++ Linux Devlopers를 설치했다면 이 과정은 무시해도 좋습니다.)

먼저 Help -> Install New Software를 Click하면 위와 같은 설치 Dialog가 표시됩니다.

위의 그림에서와 같이 Work with에서 Indigo를 선택하면 아래에 설치 가능한 Plugin의 List가 표시됩니다.

List에서 Linux Tools -> Valgrind Integration (Incubation)을 Check하고 Next를 눌러 설치과정을 모두 진행하면 기본적인 준비는 모두 완료됩니다.

Memory Leak Code

Memory Leak Code

Memory Leak을 검사하기 위한 Source Code가 위와 같다고 가정해 봅시다.

위의 Code에서 malloc() 호출 후에 System에 반환하지 않았기 때문에 Memory Leak이 발생할 것을 알 수 있습니다.

Eclipse - Profile

Eclipse - Profile

이제 이 Program을 Valgrind를 통해 Memory Leak을 검사해 봅시다. Run -> Profile을 Click합니다.

Profile As

Profile As

처음 Profile을 실행하게 되면 Profile As Dialog가 위와 같이 표시됩니다. 여기서 Profile With Valgrind를 선택하고 OK를 누릅니다.

Valgrind - Memcheck

Valgrind - Memcheck

아래의 Console View에 Program이 실행되면서 출력된 내용이 표시되고, Program이 종료된 이후에 Valgrind View에 Memory Leak이 발생한 내용이 표시됩니다.

Memory Leak이 발생한 내용을 Double-click하거나 Problems View에서 해당 Problem을 Double-click하면 위의 그림과 같이 Memory Leak이 발생한 Line이 선택되면서 쉽게 확인이 가능하게 됩니다.

7. 마치면서…

지금까지 Ubuntu에서 Valgrind를 사용하여 Memory Leak을 검사하는 여러가지 방법들을 알아봤습니다. Console 기반이라 쓰기 어렵다고 느껴질 수도 있지만, Front-end와 같이 사용하면 그다지 어렵게만 느껴지지 않을 것입니다.

Valgrind를 사용하여 Debugging과 Profiling을 수행함으로서, 개발하는 Application에 대한 안정성과 성능을 높이는 계기가 될 수 있기를 바랍니다.