라벨이 gdb인 게시물 표시

[Linux] GDB (GNU Debugger) 사용하기 - 7

이미지
  스코프 변경하기 다음 코드에서는 Depth 가 2인 함수 호출을 하게 됩니다. main( ) → func1( ) → func2( ) // frame.c # include <stdio.h> void func2 () { int b = 30 ; printf ( "func2\n" ); } void func1 () { int a = 20 ; printf ( "func1\n" ); func2(); } int main () { int n = 100 ; printf ( "Start\n" ); printf ( "[main] n = %d\n" , n); func1(); printf ( "End\n" ); return 0 ; } 각 스코프에서는 접근 가능한 지역 변수를 확인 할 수 있습니다. Break Point를 라인넘버 7에 걸고 run 커맨드로 실행 후, backtrace 커맨드로 스택 프레임을 확인 해보겠습니다. 그러면 왼쪽에 스택 프레임 넘버가 나오게 됩니다. 지금 위치한 프레임은 함수 func2( ) 스코프 이므로, 변수 b 만 확인 할 수 있습니다. 하지만, frame 커맨드 (약자 'f') 를 사용하면 스택프레임번호에 맞는 스코프에 포커싱 하여 상위 호출단의 지역변수에 접근이 가능합니다. (gdb) frame [스택프레임번호] frame 1을 입력하여 스코프를 함수 func1( ) 으로 포커싱 시킬 수 있습니다. 그러면 변수 a에 접근이 가능해 집니다. 포커싱이 func1( )에 되어있기 때문에, b 변수에는 접근 할 수 없게 됩니다. frame 2를 입력하게 되면 main( ) 함수로 포커싱 됩니다. 그러면 변수 n에는 접근 가능하나 func1 과 f

[Linux] GDB (GNU Debugger) 사용하기 - 6

이미지
  코어 덤프 프로그램이 죽었을 때, 코어 덤프를 남겨 봅시다. 쉘에서 다음과 같이 명령어를 입력 해 봅시다. ulimit -a core file size가 0 이므로, 프로그램이 죽어도 코어덤프가 생성 되지 않습니다. 그럼 core file size를 unlimited로 변경 해 봅시다. unlimit -c unlimited 그런다음 이전 포스트에서 사용 했던 코드를 사용하여 프로그램을 실행 하였을 떄 core가 생성 되는지 확인 해 봅니다. // seg_free.c # include <stdio.h> # include <stdlib.h> # include <string.h> char * str; void allocate ( void ) { str = ( char *) malloc ( sizeof ( char ) * 10 ); } void deallocate ( void ) { free (str); free (str); } void assign ( void ) { strcpy (str, "Hello World" ); } int main ( void ) { printf ( "Start\n" ); allocate(); assign(); printf ( "str = %s\n" , str); deallocate(); printf ( "End\n" ); return 0 ; } 프로그램을 실행하면, 죽고나서 core를 남깁니다. gdb에서는 이 core 파일을 가지고 디버깅 할 수도 있습니다. gdb [프로그램] core

[Linux] GDB (GNU Debugger) 사용하기 - 5

이미지
  코드 라인 추적하기 (gdb) backtrace backtrace (약자 'bt') 커맨드를 사용하면 프로그램이 중단 되었을 때 또는 현재 실행 중인 코드 위치를 확인 할 수 있습니다. 고의적으로 문제를 유발하는 코드를 작성 해 봅시다. # include <stdio.h> # include <stdlib.h> # include <string.h> char * str; void allocate ( void ) { str = ( char *) malloc ( sizeof ( char ) * 10 ); } void deallocate ( void ) { free (str); free (str); // -> 에러 발생을 위해 free를 2번 호출 하였습니다. } void assign ( void ) { strcpy (str, "Hello World" ); } int main ( void ) { printf ( "Start\n" ); allocate(); assign(); printf ( "str = %s\n" , str); deallocate(); printf ( "End\n" ); return 0 ; } gdb 로 오픈하고, run 커맨드를 입력하면 프로그램이 뻗게 되는데, 이 상태에서 backtrace 커맨드를 입력 해 봅시다. 어떤 문제로 죽었고, 어디에서 유발시켰는지 알려줍니다.

[Linux] GDB (GNU Debugger) 사용하기 - 4

이미지
  변수에 접근 되는 시점에 브레이크 포인트 걸기 (gdb) watch [변수] 변수 스코프(scope)가 매칭되어야 왓치포인트(Watchpoint)를 설정 할 수 있습니다. 즉, 전역 변수는 아무곳에서나 Watchpoint를 설정할 수 있지만, 지역 변수는 해당 변수의 scope에서만 Watchpoint를 설정 할 수 있습니다. // watch.c # include <stdio.h> int main ( void ) { int i; printf ( "Start\n" ); for (i= 0 ; i< 10 ; i++) { printf ( "i = %d\n" , i); } printf ( "End\n" ); return 0 ; } gdb로 실행 파일을 오픈합니다. 바로 Watch 포인트를 걸 수 없으므로, 우선 라인7에 브레이크 포인트를 걸고 run 커맨드로 실행을 해서, main 함수 스코프로 진입하게 합니다. 그 다음에 'watch i'를 입력하여 i 변수에 Watch 포인트를 겁니다. 브레이크 포인트와 마찬가지로 info break 커맨드를 통해 Watch 포인트도 확인 할 수 있습니다. Continue 커맨드를 입력 할 때마다, 변수 i 의 값이 바뀌는 것을 확인 할 수 있습니다. 특정 조건 만족시 Breakpoint 걸기 (gdb) break [라인넘버] if [조건] 예를 들어, 10번째 라인에 i가 5일 때 브레이크 포인트가 걸리게 하고 싶다면, break 10 if i==5 라고 입력하면 됩니다. break info 커맨드로 확인 하면 다음과 같이 나옵니다.

[Linux] GDB (GNU Debugger) 사용하기 - 3

이미지
  변수 또는 수식 출력하기 'print' 명령어를 사용 합니다. (gdb) print [변수 또는 수식] 다음 예제 프로그램 은1부터 N 까지의 합을 계산해서 리턴해주는 함수를 호출합니다. // func_sum.c # include <stdio.h> int sum ( int value) { int i, sum = 0 ; for (i= 0 ; i<=value; i++) { sum += i; } return sum; } int main ( void ) { int a = 10 ; int b = 50 ; int c = 100 ; printf ( "sum(%d) = %d\n" , a, sum(a)); printf ( "sum(%d) = %d\n" , b, sum(b)); printf ( "sum(%d) = %d\n" , c, sum(c)); return 0 ; } gdb로 열어서 list 커맨드로 라인 넘버를 확인 해 봅시다. 브레이크 포인트를 main 함수의 첫번째 라인 (17)에 걸고 run 커맨드를 실행 해 봅시다. 그런데, 10이 출력되지 않고, 이상한 값이 나옵니다. 그 이유는 브레이크 포인트는 17라인에 걸려있는데, 아직 17라인이 실행되지는 않았기 때문입니다. 따라서 next 커맨드를 입력하여, 17라인을 수행하고 나서야 변수 a 에 대한 평가가 가능해 집니다. 마찬가지로 18번째 라인에 브레이크 포인트가 걸려있으므로, b 변수를 확인 하기 위해서는 19번째로 브레이크 포인트를 옮겨야 합니다. 해당 프로그램을 그냥 실행 하게 되면, 소스코드에서 하드 코딩 된 10, 50, 100 의 인자에 대한 함수 호출 결과만 확인 할 수 있습니다. 반

[Linux] GDB (GNU Debugger) 사용하기 - 2

이미지
  Break Point 걸기 및 코드 실행하기 우선 예제파일을 먼저 만들어 봅시다. 0부터 N 까지 더해주는 프로그램입니다. 인자를 받지 않을 경우 디폴트값으로 10을 사용하게 됩니다. // sum .c int main( int argc, char **argv) { int i, sum = 0 ; int value = 1 0U; if (argc > 1 ) { value = strtol(argv[ 1 ], NULL, 10 ); } for(i = 0 ; i <= value ; i++) { sum += i; } printf( "SUM = %d\n" , sum ); return sum ; } 컴파일 해 봅시다. gcc -g sum .c -o sum gdb로 sum 실행 파일을 오픈 합니다. gdb sum list 커맨드를 입력하여 소스코드와 라인넘버를 확인 해 봅시다. 10줄이 나오는데, Enter 키를 눌러 주면 끝까지 나옵니다. 브레이크 포인트를 걸고 싶은 곳에 'break' 명령어와 라인넘버를 입력합니다. (gdb) break [라인넘버] 예를들어 6번, 9번, 19번 라인에 브레이크 포인트를 걸고 싶으면, 다음과 같이 입력합니다. ('break' 대신 약자로 'b' 만 입력 해도 됩니다.) 브레이크 포인트가 어디에 걸려있는지 중간에도 확인 할 수 있습니다. (gdb) info break 약자로 'i b' 만 입력 해도 됩니다. run 커맨드를 입력해서 브레이크 포인트가 잡히는지 확인 해 봅시다. 다음 브레이크 포인트 까지 실행 하고 싶다면, 'continue' 커맨드를 입력합니다. (약자로 'c' 만 입력 해도 됩니다.) 만

[Linux] GDB (GNU Debugger) 사용하기 - 1

이미지
  # GNU Debugger  - 프로그램 실행 중 특정 위치에서 프로그램이 어떤 상태인지 또는 어떤 동작을 하고 있는가를 감시할 수 있게 해 줌  - Segmentation Fault 등의 error도 gdb를 사용하면 쉽게 해결 할 수 있음. ( 더 이상 printf 로 스무고개 하지 말자... ) # 설치 하기 GCC (컴파일러) 설치 apt- get install gcc GDB (디버거) 설치 apt- get install gdb # 사용하기 준비 하기 아래와 같이 예제 파일을 하나 작성하고, 컴파일을 하고 실행 해 봅시다. // hello.c # include <stdio.h> int main ( void ) { printf ( "Hello World\n" ); return 0 ; } gcc hello.c -o hello gdb 실행 하기 'gdb'를 입력하여 gdb를 실행 합니다, 종료 하려면 ' quit ' 을 입력하면 됩니다. 디버깅 대상 선택 하기 2가지 방법이 있습니다.   1. gdb 실행 후, file 커맨드를 사용하여 선택하기   2. gdb 실행시 인자로 건네 주기. 코드 실행 하기 'run' 명령어를 입력합니다. (약자로 'r' 만 입력 해도 됩니다.) 코드 확인 하기 디버깅을 하기 위해서는 컴파일 시에 -g 옵션을 주어 심볼(디버깅을 위한 정보)을 포함하게 해야 합니다. gcc -g hello .c -o hello 'list' 명령어를 입력합니다. (약자로 'l' 만 입력해도 됩니다.) gdb 실행 시 인자 넘겨주기 다음 예제 코드는, 실행 시 인자를 받아서 인자 갯수를 출력 합니다.  // num_argc.c # include <stdio.h> int main ( int argc, char **argv) { printf ( "N