GDB 잘 쓰기

cinsk의 이미지
  1. GDB 잘 쓰기
  2. GDB 잘 쓰기 2: User Defined Commands

디버깅 작업 또는 프로그램의 안전성을 검사할 때 디버거를 잘 쓰면 꽤 많은 시간을 절약할 수 있습니다. 대부분 개발자들이 GDB를 써서 디버깅을 하고 있지만, GDB가 가지고 있는 강력한 기능들을 거의 쓰지 못하고 있기 때문에, 이 글에서는 자주 쓰이지는 않을 지언정, 알면 매우 도움이 되는 기능들을 위주로 살펴보겠습니다.

먼저, 이 글을 읽는 분들이 GDB의 기본적인 사용 방법 (특히 break, run, continue, file, backtrace, print 등)을 알고 있다고 가정하겠습니다. 기본적인 사용 방법을 모르신다면 Emacs/GDB/etags/cscope나 기타 GDB manual을 참고하기 바랍니다.

Breakpoints

break 명령은 대개 다음과 같이 쓸 수 있다는 것은 이미 알고 계실 것입니다:

(gdb) break                # 현재 줄에 breakpoint 설정
(gdb) break 31             # 현재 파일 31번째 줄에 breakpoint 설정
(gdb) break foo            # 함수 foo에 breakpoint 설정
(gdb) break list::next     # list 클래스 next 멤버 함수에 설정
(gdb) break hello.c:main   # hello.c 파일의 main 함수에 설정
(gdb) break util.c:300     # util.c 파일의 300번째 줄에 설정

특히 C++의 경우, 한 클래스의 모든 멤버 함수에 breakpoint를 설정하고 검사할 필요가 있는데, 이 경우, 정규 표현식(regular expression)으로 breakpoint를 설정하는 rbreak 명령을 쓰면 편리합니다. 예를 들어 보면:

(gdb) rbreak f*o           # "f*o"를 만족하는 심볼 전체에 대해 설정
(gdb) rbreak list::        # "list::.*"를 만족하는 심볼 전체에 대해 설정

특히 위 두번째 예제를 보시면 ".*"이 항상 default로 따라 온다는 것을 알 수 있습니다. 사실 rbreak 명령에 "foo"를 준 경우 사용되는 정규 표현식은, 정확히 말하면 ".*foo.*"가 됩니다. 따라서 "foo"로 시작하는 함수 전체에 대해 breakpoint를 설정하고 싶다면, 다음처럼 쓰면 됩니다:

(gdb) rbreak ^foo

breakpoint를 설정하면, 해당 breakpoint마다 번호(BNUM)가 주어지고, 이 번호를 써서 다양한 작업을 수행할 수 있습니다. 예를 들어, 전체 breakpoint 목록을 보고 싶다면:

(gdb) info b
Num Type           Disp Enb Address    What
1   breakpoint     keep y   0x08066b44 in eventShow() at menubar.cpp:1017
        breakpoint already hit 3 time
2   breakpoint     keep y   0x080b06f4 in Play() at thumbview.cpp:416
3   breakpoint     keep y   0x08066e7e in ActPlay() at menubar.cpp:1085
4   breakpoint     keep y   0x08059cd3 in Play_SS(int, int) at widgets.cpp:2183
(gdb)

첫번째 컬럼(Num)은 각 breakpoint에 대한 고유번호(BNUM)를 나타냅니다. 그리고 두번째 컬럼(Type)은 breakpoint인지 watchpoint인지 catchpoint인지를 나타냅니다. (watchpoint와 catchpoint는 다음에 설명..) 그리고 세번째 컬럼(Disp)은 이 breakpoint의 특징을 나타냅니다. (다음에 설명). 네번째 컬럼(Enb)는 현재 이 breakpoint가 활성화되어 있는지를 나타냅니다. 비활성화(n)로 표시된 breakpoint는 동작하지 않습니다. 활성화/비활성화는 'enable br [BNUM]' 또는 'disable br [BNUM]'으로 변경할 수 있습니다. 예를 들어 1번 breakpoint를 비활성화하고 싶다면:

(gdb) disable br 1

전체 breakpoint를 활성화하고 싶다면:

(gdb) enable br

2번, 4번 breakpoint를 비활성화하고 싶다면:

(gdb) disable br 2 4

2번부터 5번까지 breakpoint를 활성화 하고 싶다면:

(gdb) enable br 2-5

등으로 할 수 있습니다.

때때로, 딱 한 번만 쓸 breakpoint가 필요한 경우가 있습니다. 이 경우 쓸 수 있는 명령은 enable br once [BNUM] 또는 enable br delete [BNUM]을 쓸 수 있습니다. 예를 들어 아래 명령은 1번, 3번 breakpoint를 활성화하고, 사용된 경우 바로 비활성화시킵니다:

(gdb) enable br once 1 3

아래 명령은 4번 breakpoint를 활성화하고, 사용된 경우, 이 breakpoint를 삭제합니다:

(gdb) enable br delete 4

쓸모있는 기능 중 하나가 바로 breakpoint에 조건을 지정하고, 해당 조건을 만족할 경우에 멈추도록 하는 것입니다. 예를 들어 다음과 같은 코드가 있다고 가정해 봅시다:

int i = 0;

/* do something #1 */

for (i = 0; i < 1000; i++) {
  /* do something #2 */
  /* do something #3 */
}

이상하게도 i가 456일때 반복문 안에서 프로그램이 이상하게 동작한다고 가정해 봅시다. 이 때 "do something #2" 부분에 breakpoint를 걸었다면 (이 breakpoint의 번호는 8번이라고 가정합시다), 반복할 때마다 계속 프로그램 실행이 멈출 겁니다. 정확히 1000번 멈추겠죠. 456번까지 진행한다는 것은 매우 귀찮은 일입니다. 이 경우, 다음과 같이 조건을 지정할 수 있습니다:

(gdb) cond 8 i == 456

즉, 8번 breakpoint는 i == 456을 만족할 때에만 멈추도록 지정합니다. 조건식에는 단순한 상수 비교 이외에, 복잡한 함수 호출도 가능합니다. 예를 들면 다음과 같습니다:

(gdb) cond 8 foo(i) > bar(rand())

앞에서 예로 든 코드는 단순 반복문이기 때문에, 처음 456 - 1번에 발생하는 breakpoint는 무시하라고 지정할 수도 있습니다. 처음 N번 발생하는 breakpoint를 무시하라는 명령은 다음과 같습니다:

(gdb) ignore 8 455

즉, 8번 breakpoint는 455번 동안 무시됩니다.

또, 다음과 같은 코드를 가정해 봅시다:

int i = 0;
int j, k;
long l;

while (1) {
  j = rand();
  k = some_funtion(j, time());

  /* do something #1 */
  l = j & 0xFF00 + (int)(log(k) * 3.2108) - ...;

  if (some_condition)
    break;
}

위 코드는 j와 k가 실행할 때마다 값이 변합니다. 그리고 이상하게도 j < k 일때 변수 l이 이상한 결과를 가지는 것 같지만, 확실하지는 않습니다. 우리가 확신할 수 있는 것은 j < k일 경우, l은 항상 양수이어야 한다는 것입니다. 그래서 l의 값이 전체 반복을 끝낼 동안 어떤 값을 가지고 있는지 검사해보고 싶습니다. 이 경우 해당 breakpoint에서 멈출 때, 특정 명령을 수행하도록 하는 GDB 명령인 commands를 쓰면 됩니다.

일단 "l = j & 0xFF00..." 부분에 breakpoint를 걸고 (9번 breakpoint라고 가정), 다음 명령을 내립니다:

(gdb) commands 9
Type commands for when breakpoint 9 is hit, one per line.
End with a line saying just "end".
>silent
>if j < k
 >printf "l is %d\n", l
 >end
>cont
>end

대충 눈치가 빠른 분은 아시겠지만 'commands [BNUM] ... end'는, BNUM breakpoint에서 멈췄을 때, "..."에 지정한 GDB 명령들을 수행합니다. 일단 silent 명령으로 명령 자체가 출력되지 않도록 한 다음, GDB printf 명령으로 변수 l 값을 출력합니다. 그리고 continue 명령으로 계속 프로그램을 진행하도록 합니다. 그 결과, 프로그램을 실행할 경우, breakpoint에서 멈추고 l 값을 출력한 다음 프로그램을 자동으로 진행합니다. 이 과정은 반복문이 끝날 때까지 계속되기 때문에, 다음과 같은 비슷한 출력을 얻을 수 있습니다.

(gdb) continue
l is 3
l is -2
l is 2
l is 1
l is -3

앞에서 j < k일 때, l은 항상 양수여야 한다고 말했습니다. 위 결과를 보고 우리는 l 값이 때때로 잘못된다는 것을 쉽게 알 수 있습니다.

commands에 쓸 수 있는 GDB 명령어 형태는 다음 기회에...

가끔 next나 step으로 실행 과정을 따라 가다가 반복문을 만날 경우, 반복문 끝난 부분으로 바로 건너뛰거나, 현재 함수의 실행을 정상적으로 끝내고 상위 함수로 돌아가야할 경우가 있습니다. 예를 들어:

for (i = 0; i < 1000; i++) {
  /* do something #1 */
  /* do something #2 */
}
/* do something #3 */

현재 "/* do something #2 */" 부분까지 실행했고, 이 반복문에 이상이 없다고 판단되면, 반복문 다음까지 빠르게 진행하고 싶을 겁니다. 이 경우, until 명령이나 advance 명령을 쓰면 편리합니다.

until 명령을 쓰면, 반복문이 아닌 경우에는 next 명령과 똑같이 동작합니다.

(gdb) until

반복문일 경우, 현재 스택 프레임 (즉, 현재 함수) 안에서, 현재 줄 다음 줄에 올 때까지 프로그램을 실행합니다. 쉬운 말로, 루프를 진행하고 빠져 나오는 순간까지 실행한 다음 "(gdb)" 프롬프트를 보여줍니다.

advance 명령은 continue 명령과 마찬가지로 프로그램을 주욱 실행시키는 대신, 지정한 곳에 코드 흐름이 오면 바로 멈춥니다. 예를 들어 위 코드의 "/* do something #3 */" 부분의 줄 번호가 34였다면, until 명령 대신 다음과 같이 실행할 수도 있습니다:

(gdb) advance 34

advance 명령은 스택 프레임에 대한 제한이 없기 때문에, 현재 함수가 아닌, 아무 곳이나 설정할 수 있으며, 위치 지정은 줄 번호 뿐만 아니라, break 명령에 쓰는 모든 형식을 다 지원합니다.


네트워크로 서비스 요청 데이터를 전송받아 분석하고, 적절한 기능을 수행하고, 그 결과를 돌려주는 서버 프로그램을 생각해 봅시다. 그리고 다음과 같은 꼴로 되어 있다고 가정해 봅시다:

#define PACKET_MAX      10

int
fetch(void)
{
  int packet_received = 0;
  int received[PACKET_MAX];

  while (1) {
    if (!packet_received) {
      if (recv_data(received, PACKET_MAX) == 0)
        packet_received = 1;
    }

    /* do work here */

    process_packet(received, PACKET_MAX);
  }
  return 0;
}

이 프로그램은 평소에는 정상적으로 잘 동작하지만, 특정 패킷을 받으면 이상하게 동작한다고 가정합시다. 그리고 이 패킷은 아주 가끔 들어온다고 가정해 봅시다. 원하는 대로 패킷을 보내주는 프로그램을 따로 작성해 두지 않았다면, 이 프로그램을 디버깅하기 위해서, 문제를 일으키는 패킷이 올 때까지 하염없이 기다려야할 지도 모릅니다. 실제 코드는 다음과 같습니다:

만약 원하는 패킷이 recv_data()를 통해 들어왔다고 가정합시다. 이 때 packet_received는 1이 되고, 그에 따라 처리 작업이 이상하게 동작할 것입니다. 이 때, received의 내용을 저장하기 위해, 다음 명령을 쓸 수 있습니다:

(gdb) dump binary value buggy.dat received

위 명령을 수행하면 배열 received의 내용을 파일 buggy.dat에 저장합니다. 만약 시작 주소와 끝 주소를 알고 있다면 다음 명령을 쓸 수 있습니다:

dump binary data buggy.dat START-ADDR END-ADDR

이 때, START-ADDR는 시작 주소를, END-ADDR는 끝 주소를 나타냅니다. 즉, 앞 received 배열의 경우, 다음과 같이 쓸 수 있습니다.

(gdb) dump binary memory buggy.dat received received+10

어느 방법을 썼든지, 현재 디렉토리에는 buggy.dat이라는 파일로, 배열 received의 내용이 저장될 것입니다. 이는 메모리 내용을 그대로 dump시킨 것이므로 od(1)와 같은 툴을 써서 그 내용을 직접 볼 수 있습니다. received 배열은 int 배열이므로 다음과 같이 확인 가능합니다:

$ od -td buggy.dat 
0000000         163         151         162          85
0000020          83         190         241         252
0000040         249         121
0000050
$ _

만약, 바로 디버깅을 성공적으로 끝냈다면, 사실 위와 같은 기능은 큰 역할을 발휘하지 못합니다. 하지만, 계속해서 디버거를 실행해서 여러번 디버깅을 해야 한다면 꽤 쓸모있다는 것을 알 수 있습니다.

일단, 새로 GDB를 띄워 디버깅을 시작했다고 합시다.

    if (!packet_received) {

위 코드를 실행할 때, 강제로 packet_received를 1로 만들어, 패킷을 받는 부분을 건너뜁니다. 변수의 값 변경은 print 명령으로 쉽게 할 수 있습니다:

(gdb) p packet_received = 1

그리고 나서, received 배열을 아까 저장해 두었던 buggy.dat에서 다음과 같이
불러올 수 있습니다:

(gdb) restore buggy.dat binary received
Restoring binary file buggy.dat into memory (0xbfeda890 to 0xbfeda8b8)

이 외에도, GDB는 타 디버거에 비해 강력한 기능들을 많이 제공합니다. 다음 기회에 좀 더 알아보겠습니다.

댓글

lovian의 이미지

안그래도 GDB 사용 해야지 해야지 생각만 하고 있었는데,
계기로 삼아야겠습니다. :)
-----------------
한글을 사랑합니다.

-----------------
한글을 사랑합니다.

recypace의 이미지

메뉴얼을 제대로 안보고 필요한 기능만 참고썼는데 감사합니다. 인내가 강하다고 해야하는지 무식하면 몸이고생한다고 해야할지. 쏙쏙 필요한 기능들만 아주 확실하게 정리해주셨네요. :-)

conan의 이미지

gdb를 익혀볼까 하다가 그냥 바로 DDD로 넘어갔습니다. 일반 터미널 환경이라면 어쩔수 없지만 cgywin의 xwindow를 이용해서 어지간한 환경에서는 무리 없이 사용하고 있습니다.

한가지 cygwin의 xwindow를 이용해서 접근하면 표준출력이 나오지 않더군요. 어떻게 해야 하는지...

High Risk & High Return ~

MasterQ의 이미지

정말 도움이 많이 되겠군요, 좋은 정보 고맙습니다.

서지훈의 이미지

정말 코어만 ㅋㅋ
좋은 정보 감사...

<어떠한 역경에도 굴하지 않는 '하양 지훈'>

#include <com.h> <beer.h> <woman.h>
do { if (com) hacking(); if (money) drinking(); if (women) loving(); } while (1);

#include <com.h> <C2H5OH.h> <woman.h>
do { if (com) hacking(); if (money) drinking(); if (women) loving(); } while (1);

초코리의 이미지

GDB기초적인것 밖에 못썼는데..

좋은 정보 감사합니다..

xx1의 이미지

정말 좋은 정보 감사합니다. : )

ctcquatre의 이미지

좋은 자료, 잘 보겠습니다.

감사합니다.

Chaos to Cosmos,
Chaos to Chaos,
Cosmos to Cosmos,
Cosmos to Chaos.

Chaos to Cosmos,
Chaos to Chaos,
Cosmos to Cosmos,
Cosmos to Chaos.

mach의 이미지

멋진 글입니다.
감사합니다.

------------------ P.S. --------------
지식은 오픈해서 검증받아야 산지식이된다고 동네 아저씨가 그러더라.

------------------ P.S. --------------
지식은 오픈해서 검증받아야 산지식이된다고 동네 아저씨가 그러더라.

binaa1의 이미지

예전부터 언제나 좋은 내용으로 지식을 나누어 주시니 고맙습니다.

sangwoo의 이미지

디버깅할 때 큰 도움이 될 것 같습니다. :-)
감사합니다.

----
Let's shut up and code.

----
Let's shut up and code.

falaris의 이미지

언제나 좋은 글 감사 합니다!!!

--------------@@
젠투교+emacs교로 서서히 가는중!~@

GjtRoql의 이미지

좋은 글입니다.
감사합니다.
도움 많이 됐습니다.

인생의 목표는 행복! 행복하기 위해 일할것인가! 그 일을 하므로서 행복해질것인가!

--------------
Burning Blue!
--------------

jyoung의 이미지

KLDP에 글 보관 기능을 첨 쓰게 됐네요.
GDB의 유용한 기능들을 정말 일목요연하게 잘 정리하셨네요. 두고두고 참고자료로 쓰겠습니다. :)

---
될대로 되라지.

될대로 되라지..

revizes의 이미지

아자씨..indent 2칸인건 여전하군..-_-

다 덤벼! 다 받아줄께!!

다 덤벼! 다 받아줄께!!

sunyzero의 이미지

깔끔하게 정리해주셨네요.

rbreak 는 모르던 기능인데, 새로운 것을 알았네요. 감사합니다.

네트워크 서버등을 볼때는 bit계산이나 8진수로 봐야할때가 종종 생기죠. 이럴때 print 명령에
포매팅을 하면 좋은데 많은 분들이 쓰지 않더군요.

예를 들어 rts_mask 라는 곳에 값을 p rts_mask 하면 값이 그냥 10진수로 출력되지만,
p/t rts_mask 하면 2진수로 출력되죠.

주소값의 내용을 출력하는 x 명령도 x &buf 하면 그냥 buf 의 내용을 형에 따라서 출력하지만,
x/wx &buf 하면 buf에서 w(word)사이즈만큼 x(hex) 출력으로 출력하죠. 이런식으로
x/20bt 0xe1b40123 하면 해당 주소에서 20b(20바이트)를 로 인해서 2진수(t)로 출력해주죠.

gdb는 참 쓰면 쓸수록 dbx보다 좋은것 같습니다. 솔직히 dbx로 디버깅할려면 너무 힘들어요.
의외로 old version의 dbx를 쓰시는 업체도 많은듯 싶습니다. 좀 gdb좀 깔아주면 덧나낭... -_-;;

PS) 이외에 gdb는 명령어를 안치고 그냥 엔터만 쳐도 이전 명령어가 반복되는데,
이거 몰라서 계속 n 치는 분도 많이 봤습니다.
========================================
* 부분이 전체를 대변하는 하나의 속성일때 진리이다.
영속적이지 못한 것은 전체가 될 수 없다.

========================================
* The truth will set you free.

dhmk의 이미지

좋은글 잘 봤습니다.

혹시 프로그램에서 명시적으로 디버거상태로 전환하도록 할 수 있나요?

조금 성격은 다르지만 파이썬에서는 pdb.set_trace() 하면

디버거 상태로 빠집니다.

C, C++로 프로그램시 위와같이 할 수 있는지 궁금합니다.

정확히 실행해야하는 프로그램에서 예외상황이 발생했을 때,

더이상 진행(혹은 정지)하지않고 운영자가 상황에 따라 (변수등을 수정하고)

작업을 재개하도록 하려고 합니다.

전 아직까지 방법을 찾지 못했는데, 혹시 방법이 있다면 알려주시기 바랍니다.

codebank의 이미지

사실 breakpoint 때문에 거의 사용을 못했었는데 이렇게
자세히 설명해 놓으니 쉽게 이해가 가네요.
------------------------------
좋은 하루 되세요.

------------------------------
좋은 하루 되세요.

nomoreid의 이미지

위 분이 원하시는건 프로그램 실행도중에 특정 상황에 gdb로 자동 attach 되는걸 원하시는거 같은데 아래기능을 통해서 특정 상황에 자신의 process id 를 걸고 gdb를 실행해 주는 형태로 프로그램을 구현하면 가능할수도 있을거 같습니다.

gdb 실행파일이름 processid

이렇게 하면 해당 processid 로 attach 상태가 됩니다. 프로그램은 일시 멈춤 상태가 됩니다.
이때 'generate-core-file' 명령으로 강제로 코어 파일을 만들 수 있습니다.
'c'를 입력하면 gdb가 attach 된 상태에서 continue 상태가 되겠죠.
'detach' 또는 'quit' 하면 detach 되서 gdb를 실행하기 전 상태로 복귀 됩니다.
'kill' 명령으로 프로세스를 죽일 수도 있습니다.

ps -ef |grep session_dbg
root     24113  8440  0 Jul04 pts/15   00:05:50 ./session_dbg
 
.....................................
 
gdb session_dbg 24113
GNU gdb Red Hat Linux (6.1post-1.20040607.41rh)
.....................................
0x006be7a2 in _dl_sysinfo_int80 () from /lib/ld-linux.so.2
(gdb) bt
#0  0x006be7a2 in _dl_sysinfo_int80 () from /lib/ld-linux.so.2
#1  0x00760110 in __nanosleep_nocancel () from /lib/tls/libc.so.6
#2  0x007955fa in usleep () from /lib/tls/libc.so.6
#3  0x08065980 in CMainApp::MainLoop (this=0x8281e20) at MainApp.cpp:262
#4  0x080646fa in main (argc=1, argv=0xfeec73d4) at Main.cpp:26
(gdb)generate-core-file
Saved corefile core.24113
(gdb) c
Continuing.
 
"ctrl + c"
 
Program received signal SIGINT, Interrupt.
0x006be7a2 in _dl_sysinfo_int80 () from /lib/ld-linux.so.2
(gdb) quit
The program is running.  Quit anyway (and detach it)? (y or n) y
Detaching from program: /pmang/rnr2/r2b2_session9_dbg2, process 24113

Never Ending 삽질.

dhmk의 이미지

답변 감사합니다. PID를 통해 디버깅하는것도 몰랐는데 많은 도움이 됐습니다.
그런데 제가 질문드리고자 하는 것은 프로그램에서 직접 디버깅 프로그램을 호출(?)
할 수 있는지 여부입니다.

위에서 예로 드린 파이썬의 set_trace()로 다시 질문드리자면

import pdb

...... #일련의 처리
if error == 1:
pdb.set_trace()

라고 하면 프로그램 실행중에 error가 1이면, 디버깅상태로 사용자 입력을 기다립니다.
혹시 Unix환경에서 C나 C++로 이런 처리가 가능한지 궁금합니다.

sphawk의 이미지

리눅스 쪽은 안 해봐서 모르겠지만, 윈도우쪽 프로그램은
프로그램 로직 내에서 __asm { int 3 }; 을 호출하면
자동으로 기본 디버거를 호출해서 디버깅 할 수 있습니다.
(프로그램에 예외가 발생해서, 디버깅하시겠냐고 물어보지요.)

이때 디버깅 하겠다고 한다면, Visual C++ 같은 IDE나
WinDBG같은 디버거가 깔려 있으면 자동으로 그 디버거가 실행됩니다.
디버그 모드로 빌드된 프로그램이고, 소스가 제 경로에 있다면 소스 위치 등도 잘 보입니다.
릴리즈 모드일 경우에는 제대로 보이지 않지요; 어셈블리 코드만 덜렁...

그리고 디버그가 끝난 후에 process를 디버거에서 detach 시키고
계속 진행할 수도 있고.. process를 종료시킬 수도 있습니다.
유닉스쪽은.. 잘 모르겠군요. 누군가 답변을 주시겠죠?..

// 추가

아.. 생각해보니 유닉스에서는, 디버거를 실행해야 할 상황에서
gdb 실행파일이름 processid 명령을 system 같은 호출로,
자기 프로세스 아뒤를 호출해버리면 되지 않을까요?..
디버거 종료시까지 로직이 멈추겠지만, 어차피 파이썬도 마찬가지일듯 하고
목적은 값 찍어보시려는 거 같으니.. 그정도면 충분하지 않을까요?..

dhmk의 이미지

말씀하신데로 한번 해봐야 겠네요. 답변 감사합니다.

missu의 이미지

몇번 gdb 써볼려고 문서도 읽어보고 했는데, 번번히 잘 이해가 가지 않아서 때려치고 다시 보고 다시 때려치고 했는데,
이해하기 쉽게 잘 적어주셔서 정말 감사합니다.
그리고 최근에 다시 C FAQ 를 봤는데,

int a[] = "12345";
3[a] == a[3] 인것은 정말 충격이었습니다.

계속 좋은 글 적으시길 응원합니다~ ^.^

공부허자

=====
공부허자

heedae의 이미지

gdb 쓸때...정말정말 기본적인 기능들만 원시적으로 사용하고 있었는데...이런 지능적인 플레이가 가능했군요
감사히 보고 사용하겠습니다..

오늘부터나는@.@

opensrc의 이미지

저는 주로 DDD(Data Display Debugger)로 GDB를 이용합니다.
자료구조를 display 하면서 디버깅을 하고 있는데,
제 느낌에 DDD가 GDB 보다 좀 더 디버깅에 집중할 수 있는 것 같습니다.
CUI만 가능한 환경이라면 선택의 여지가 없겠지만,
저는 늘 X-환경을 이용하거든요.
혹시 DDD도 사용하신다면 DDD에 대한 의견도 듣고 싶습니다.
다른 분들은 DDD는 사용 안하시나요?

지리즈의 이미지

GDB를 사용한다고 말합니다.

정확히 말하면, GDB의 프론트엔드로서 DDD를 사용한다고 해야 하겠죠.

DDD나름대로 좋은 기능이 많은 것으로 알고 있지만...
사실 GUI환경에서 GDB프론트엔드 이상으로는 사용하지 못하고 있네요.

그러나 저렇나
쓰레드 디버깅은 정말 어렵네요.

아주 섬세한 차이로 시그널 순서가 어긋나는 문제인데...
이게 디버거로 돌리거나, 혹은 디버그 메시지같은 것을 삽입하면,
결과가 달라져 버립니다.

거의 1주일째 요문제 때문에 씨름하고 있는데, 아~ 죽겠습니다.

There is no spoon. Neo from the Matrix 1999.

There is no spoon. Neo from the Matrix 1999.

ssoo76의 이미지

(gdb) break 'XXX{TAB}....

해보세여.... ' 문자를 입력한 이후에는 TAB을 이용해서 자동 확장도 됩니다.....

마지막은 ' 문자로 닫아주는 쎈스까지....

세상은 하나..........

세상은 하나..........

jg의 이미지

요즘 GDB에 대해 보고 있었는데 고맙습니다.
제가 자주가는 싸이트에 링크를 걸었는데 괜찮겠지요?

http://esc.kau.ac.kr/moniwiki/wiki.php/GDB?action=show#s-5.1

$Myoungjin_JEON=@@=qw^rekcaH lreP rehtonA tsuJ^;$|++;{$i=$like=pop@@;unshift@@,$i;$~=18-length$i;print"\r[","~"x abs,(scalar reverse$i),"~"x($~-abs),"]"and select$good,$day,$mate,1/$~for 0..$~,-$~+1..-1;redo}

익명 사용자의 이미지

어려운 길을 걷는 것이 고되지만 즐겁고 의미 있는 길임을 느낍니다.

antz의 이미지

좋은 글 감사합니다. :-)

---


Jabber: lum0320@jabber.org

ikpil의 이미지

오래된 정보라도 필요했기에 소중하며, 회손되지 않게 보관해준 KLDP도 소중합니다.
감사합니다.

kdh0404의 이미지

+1 꾹 누르고 갑니다.

좋은 글 감사합니다~

-----
Do It Now!


-----
Do It Now!

canejune의 이미지

좋은 글 감사합니다. : ) 큰 도움 --b

paeksj98의 이미지

사용법을 몰랐는데 이글을 보고 도움을 많이 받았습니다.

익명 사용자의 이미지

은혜롭습니다. 감사히 사용하겠습니다.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.