간단한 captcha 는 기계적으로 풀어버리는 소스.

http://kthan.tistory.com/176

 

음....

 

파이선 말고 php 로는 구글에 이런것도 있음..

http://code.google.com/p/cool-php-captcha/

 Centos 에서 Objective-c 와 gcc 설치 법...

 

 

 

Windows에서 개발을 한 경험이 있는 분들이라면, AQTime(예전 이름은 Memproof)이라는 상용 Tool을 잘 아실 것입니다.

AQTime은 Runtime 검사를 통해서 Application의 Performance를 진단하고 Memory Leak(Heap Memory를 할당했을 경우 사용 후에 System에 반환하지 않아서 발생하는 누수현상)을 검사할 수 있는 유명한 Profiling Tool입니다.

이러한 Profiling Tool을 사용하면 개발자가 미처 파악하지 못한 Application의 문제를 해결하고 Performance를 향상시킬 수 있기 때문에 Project의 안정화 시에 주로 사용됩니다.

이번 Post에서는 이와 비슷한 기능을 Linux에서 수행하는 Command-line Tool인 Valgrind를 통해서 Memory Leak을 검사하는 방법을 알아보도록 하겠습니다.

Table of Contents [Show]

1. Valgrind?

Valgrind는 앞서 말한 대로 Linux Program의 Profiling을 위한 Application입니다. (지원하는 Platform과 Architecture를 확인하려면 여기를 방문하면 됩니다.) 그리고 License가 GPL이기 때문에 AQTime과 달리 사용하는데 전혀 비용이 들지 않습니다.

또한 수많은 Open-source Project가 Valgrind를 통해서 Debugging과 Profiling을 수행하고 있다는 것은 이 Program의 정확성과 안정성을 증명합니다.

Valgrind는 엄밀하게 말하면 Profiling Suite로 여러가지 Profiling을 위한 도구를 포함하고 있으며 각각의 도구는 valgrind 명령을 통해 통합되어 수행됩니다. 그 중 일부를 소개하면 다음과 같습니다.

  • Memcheck: Memory 관리의 문제를 진단하는 Tool입니다. 할당받지 않은 Heap Memory에 접근하는 것이나 Memory Leak과 같은 문제를 이 Tool을 통하여 발견할 수 있습니다.
  • Callgrind: Runtime 시에 각 함수의 호출 history와 실행 Function간의 Call Graph를 만들기 위한 정보를 기록하는데 사용하는 도구입니다. 저장된 내용은 Command-line Tool이나 KCachegrind를 통해서 분석할 수 있습니다. KCachegrind에 대해서는 이후에 간단한 사용법을 설명하겠습니다.
  • Massif: Heap Memory에 대한 사용 정보를 확인할 수 있습니다. 간단한 예제와 설명은 여기를 참고하기 바랍니다.
  • Helgrind: POSIX Thread(간단히 PThread)를 Program에서 사용할 때 각 Thread간의 동기화와 관련된 문제를 진단하기 위한 Tool입니다.

Valgrind는 좋은 Tool이지만 사용할 때 유의할 점이 있습니다. Valgrind는 Code 상의 오류를 검사할 수 있지만, 문맥적인 오류는 잡아내지 못합니다. 다시 말하면, 기술적으로 해당 Program이 문제가 없다는 것을 증명할 수는 있지만, 실제 그 Program이 사용자가 원하는 대로 제대로 동작한다는 것을 증명할 수 없다는 것입니다. 생각 외로 이런 Profiling Tool을 과신하는 경우가 종종 있는데 그런 점은 조심해야 합니다.

좀 더 자세한 Valgrind의 정보를 얻기 원한다면 다음 Link를 방문하기 바랍니다.

2. 설치

Valgrind를 설치하는 것은 간단합니다. Terminal을 새로 열어서 다음과 같이 입력하여 설치합니다.

1
sudo apt-get install valgrind

다음 Section에서는 Test Program을 Build하면서 설명을 진행합니다. System에 Build를 위한 Package가 설치되어있지 않다면 다음과 같이 입력하여 설치합니다.

1
sudo apt-get install build-essential

3. Memory Leak 검사하기

Valgrind가 무엇인지에 대해서 알아봤고 설치도 마쳤으니, 이제 Test Program을 만들어서 Valgrind의 Memcheck 도구를 사용하여 Memory Leak을 검사하는 방법을 알아봅시다.

Gedit나 Vim과 같은 편집기를 사용해서 다음과 같은 내용을 입력한 후 test.c라고 저장합시다.

1
2
3
4
5
6
7
8
9
10
11
12
#include <stdlib.h>

void test(void)
{
    char *= malloc(sizeof(char) * 10);
}

int main(void)
{
    test();
    return 0;
}

위의 C Code를 보면 test()에서 malloc()을 통해서 Heap Memory를 할당받았지만 사용 후에 free()를 사용하여 System에 반환하지 않았기 때문에 Memory Leak이 발생하는 것을 알 수 있습니다.

이제 이 Source를 Compile해 봅시다. Terminal에서 다음과 같이 입력하여 Debugging이 가능하도록 Option을 적용하여 Compile합니다.

1
gcc -g -o test test.c

test.c를 Compile하여 생성된 test라는 실행 File에 대해서 이제 Valgrind를 사용하여 Memory Leak을 검사해 봅시다. Terminal에서 다음과 같이 입력하여 Valgrind를 실행합니다.

1
valgrind --leak-check=yes ./test

만약 Memory Leak을 검사할 Program이 Argument(명령행 인자)를 가지고 있다면, 위의 명령에서 검사할 Program 뒤에 그대로 이어서 적으면 됩니다.

위의 명령을 실행하면 먼저 test Program이 실행되고 종료된 후에 Valgrind가 검사한 정보가 Terminal에 출력됩니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
==8067== Memcheck, a memory error detector
==8067== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al.
==8067== Using Valgrind-3.6.1 and LibVEX; rerun with -h for copyright info
==8067== Command: ./test
==8067== 
==8067== 
==8067== HEAP SUMMARY:
==8067==     in use at exit: 10 bytes in 1 blocks
==8067==   total heap usage: 1 allocs, 0 frees, 10 bytes allocated
==8067== 
==8067== 10 bytes in 1 blocks are definitely lost in loss record 1 of 1
==8067==    at 0x4C28FAC: malloc (vg_replace_malloc.c:236)
==8067==    by 0x400505: test (test.c:5)
==8067==    by 0x400514: main (test.c:10)
==8067== 
==8067== LEAK SUMMARY:
==8067==    definitely lost: 10 bytes in 1 blocks
==8067==    indirectly lost: 0 bytes in 0 blocks
==8067==      possibly lost: 0 bytes in 0 blocks
==8067==    still reachable: 0 bytes in 0 blocks
==8067==         suppressed: 0 bytes in 0 blocks
==8067== 
==8067== For counts of detected and suppressed errors, rerun with: -v
==8067== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 4 from 4)

위의 내용은 Valgrind를 실행하여 얻은 출력화면입니다. 중요한 부분은 11~14번째 Line에 있는 Memory Leak정보로, 이것은 test.c의 5번째 줄에 위치한 test()의 Code에서 Memory Leak이 발생했다는 것을 나타냅니다.

이와 같이 Memory Leak 정보에 표시된 Call Stack을 통해서 Source Code의 어느 함수의 몇번째 Line에서 Memory Leak이 발생했는지를 확인할 수 있습니다.

유의해야할 점은, Valgrind는 검사할 Program을 실행한 상태(Runtime)에서 검사하기 때문에 실행 시에 수행되지 않은 Code에 대해서는 검사할 수 없다는 것입니다. 그래서 Test Case를 잘 수행하지 않으면 Memory Leak을 검사하지 못할 수 있기 때문에 실행하기 전에 Test Case를 미리 준비하는 것이 좋습니다.

4. 마치면서…

지금까지 Valgrind를 사용하여 Memory Leak을 검사하는 방법을 간단하게 알아봤습니다. 다음 Post에서는 Valgrind의 Front-end를 사용하여 좀 더 쉽게 Memory Leak을 검사하는 방법과 Eclipse CDT로 Program을 개발했을 때 Eclipse 상에서 Valgrind를 사용하는 방법에 대해서 알아보도록 하겠습니다.


출처 : http://ioriy2k.pe.kr/archives/3754

출처 : http://sunjinyang.wordpress.com/2009/06/18/debugging-memory-leaks-with-tcmalloc-google-perftools/


리눅스에서 메모리 침범이나 메모리 누수, 혹은 복잡한 메모리 접근 관련 오류를 디버깅할때는 대부분 Valgrind 도구를 이용합니다. 하지만 Valgrind는 많은 메모리를 사용하고 실행 속도가 현저하게 느려지기 때문에, 별도의 타겟 장비에서 제한된 조건으로 동작하는 어플리케이션에는 조금 무리가 있습니다. 게다가 Valgrind의 메모리 검사 도구는 프로그램이 종료된 시점에서 누수된 메모리만 찾기 때문에, 실행 중에는 엄청나게 메모리를 사용하다가 정상적인 객체 해제 루틴이 호출되면 모든 메모리가 정리되어 찾을 수 없는 경우는 발견하지 못합니다.

구글 성능 도구를 다시 검토하고 사용하게 된 이유도 바로 여기에 있습니다. 현재 디버깅 중인 프로그램의 문제가 대략 이렇습니다. 몇날 며칠이고 문제없이 가동해야 하는 프로그램이 특정 설정을 적용한 후에는, 자고 일어나면 10~20메가씩 메모리 점유율이 한꺼번에 올라갑니다. 하지만 Valgrind 도구를 사용해도 어느 부분이 문제인지 찾을 수가 없습니다. 지난 글에서 TCMalloc 메모리 할당자로 교체한 후 문제가 해결된 줄 알았던 바로 그 패턴이기도 합니다. 그래서 이번에는 프로파일 기능을 이용해 직접 메모리 누수를 디버깅 해보고, 나중을 위해 그 과정을 정리해 보았습니다.

디버깅 환경

디버깅 환경은 우분투 9.04 x86_32 플랫폼입니다. x86_64 플랫폼에서는 이상하게 호출 그래프가 그려지지 않아서 일단 무시했습니다. 사용한 버전은 공식 홈페이지에서 다운로드 받은 1.2 버전입니다. 1.3 버전은 이상하게 프로파일 기능이 동작하지 않아 역시 무시했습니다.

TCMalloc 도구 설치 및 연결

호출 그래프를 생성하기 위해 dot 프로그램이 필요한데 이 프로그램은 graphviz 패키지에 들어있으므로 설치해야 합니다.

$ sudo apt-get install graphviz

우선, 공식 홈페이지에서 google-perftools 압축 파일을 다운로드 한 뒤 다음과 같이 빌드하고 설치합니다. [2011.05.02 추가]INSTALL 문서에도 명시되어 있듯이, x86_64 환경에서는 libunwind 라이브러리를 미리 설치한 뒤 빌드해야 정상적으로 동작합니다.

$ cd google-perftools*
$ ./configure --prefix=/usr
$ make
$ sudo make install

TCMalloc 라이브러리를 연결하는 방법은 공식 문서에도 나와 있듯이 디버깅할 프로그램 링크 마지막에 ‘-ltcmalloc‘ 옵션을 추가하거나, 실행할때 프로그램 앞에 ‘LD_PRELOAD=/usr/lib/libtcmalloc.so execute-file‘ 처럼 라이브러리를 먼저 로드해주면 됩니다. 저는 첫번째 방법을 사용했습니다. [2011.05.02 갱신] 언제부터인지는 확실치 않지만 첫번째 방법은 동작하지 않고 두번째 방법으로 해야 메모리 프로파일이 정상적으로 동작합니다.

참고로, 디버깅할 프로그램을 컴파일할때는 디버깅 심볼 옵션(-g)이 있어야 호출 그래프에서 정확한 함수 이름이 표시됩니다. 또한 최적화 옵션(-O2 등)을 사용 안하면 더 정확한 함수 호출 그래프를 얻을 수 있습니다.

프로파일 데이터 얻기

TCMalloc 라이브러리를 연결해도 기본적으로 프로파일 기능은 동작하지 않습니다. HEAPPROFILE 환경변수에 프로파일 정보를 주기적으로 덤프할 파일 이름 접두사(prefix)를 지정해야만 동작합니다.

$ HEAPPROFILE=/tmp/profile execute-file

접두사는 파일 절대 경로로 디렉토리를 포함할 수 있습니다.

만일 덤프 파일이 너무 자주 생성되거나 반대로 너무 드물게 생성된다면 환경 변수를 통해 간격을 조절할 수 있습니다.

$ HEAPPROFILE=/tmp/profile 
  HEAP_PROFILE_ALLOCATION_INTERVAL=107374182400 
  execute-file

더 자세한 옵션은 공식 문서를 확인해 보시기 바랍니다.

위 예제에서 지정한 방식대로 프로그램을 실행하면 /tmp/profile.0001.heap/tmp/profile.0002.heap/tmp/profile.0003.heap 등과 같은 프로파일 덤프 파일이 실행 도중 계속 생성됩니다.

결과 그래프 얻기

포스트스크립트(PostScript) 파일 형식으로 메모리 프로파일 정보를 포함한 함수 호출 그래프를 얻으려면 다음과 같이 형식으로 pprof 프로그램을 실행하면 됩니다.

$ pprof --ps --lines 
    execute-file 
    /tmp/profile.0001.heap 
    > profile-0001.ps

프로파일 덤프 파일에 대하여 하나씩 그래프를 생성해 직접 눈과 손으로 비교하는 것도 나쁘지 않지만, 두 프로파일의 차이점만 그래프로 만들어주는 옵션이 있으므로 이를 사용하면 더 편리합니다. 즉, 시간대별 메모리 사용량의 달라진 부분이 정확하게 어느 함수 호출 때문인지 알 수 있게 해줍니다.

$ pprof --ps --lines 
    --base /tmp/profile.0001.heap 
    execute-file 
    /tmp/profile.0002.heap 
    > profile-0002-diff.ps

물론, PDF(--pdf), GIF(--gif) 등과 같은 다른 형식으로 그래프 파일을 얻을 수도 있습니다. 더 자세한 옵션은 ‘pprof --help‘를 참고하시면 됩니다.

결론

며칠간 디버깅에 적용해보니 문제가 발생한 패턴이 무엇이었는지도 찾아내고, 간과했던 작은 메모리 누수 버그들도 함께 발견할 수 있었습니다. 하지만, 언제나 그렇듯이, 디버깅 사태까지 오기 전에 더 튼튼하게 설계하고, 더 꼼꼼하게 프로그래밍하고, 더 철저하게 코드 리뷰와 테스트를 거치는 게 정도임을 새삼 깨닫습니다.

출처 : http://blog.daum.net/jchern/13756799


download : http://code.google.com/p/google-perftools/downloads/list

toturial : http://google-perftools.googlecode.com/svn/trunk/doc/cpuprofile.html

 

설치방법

tar -zxvf google-perftools-1.6.tar.gz

cd google-perftools-1.6

./configure

make

su

make install

 

 

사전 작업

1. 프로파일링을 워하는 프로그램 컴파일시에 -lprofiler를 같이 컴파일한다.

2. <google/profiler.h>를 include한다

 

bash >

export LD_LIBRARY_PATH=/usr/local/lib

export CPUPROFILE=output.txt( CPUPROFILE로 설정된 파일명으로 출력파일이 생성된다 )

 

특정 함수에 대해서만 프로파일링을 하기 위해서는

ProfilerStart()와 ProfilerStop()를 사용하면 된다.

ProfilerStart()에는 함수명을 파라미터로 준다.( ProfileStart("test_func"); )

여기까지 설정한후에 실행을 하면

CPUPROFILE에 설정한 파일명으로 파일이 하나 생성이 된다.

이파일은 바이너리 포맷이라서 그냥 볼수는 없고

 

/usr/local/bin/pprof 라는 파일로 볼수 있다.

/usr/local/bin/pprof [실행파일명] [output.txt]

(pprof)라고 프로프트가 뜨면 top를 입력

 

(pprof) top

 

상위에 노출되는 함수들이 실행시간이 오래걸리는 함수들이다.

 

 

 

특정 함수에 대한 프로파일링 :

pprof    --gv --focus=함수명   실행파일 출력파일

 

특정 함수를 제외한 프로파일링

pprof   --gv --ignore=함수명  실행파일 출력파일


 

좀더 자세한 내용은 요기서 ; http://google-perftools.googlecode.com/svn/trunk/doc/cpuprofile.html

 

+ Recent posts