[an error occurred while processing this directive]

[an error occurred while processing this directive]

Debug tips (C/C++)

C‚ðŽg‚¤ŒÀ‚è”ð‚¯‚Ä’Ê‚ê‚È‚¢‚Ì‚ªƒfƒoƒbƒO‚̈ï‚Ì“¹c

‚Ü‚¸‚ÍprintfƒfƒoƒbƒO

ƒfƒoƒbƒO‚ÌŠî–{‚́A‚ǂ̕ϐ”‚É‚Ç‚±‚ʼn½‚ª“ü‚Á‚Ä‚é‚©‚ð‚¿‚á‚ñ‚Æ”cˆ¬‚·‚邱‚ƁB •Ï‚È‹““®‚ª‚ ‚Á‚½‚çA‚Æ‚è‚ ‚¦‚¸‚ ‚¿‚±‚¿‚Éprintf‚ð“ü‚ê‚Ä‚Ý‚éB ‚±‚Ì‚Æ‚«A‰üs‚ào—Í‚³‚¹‚È‚¢‚ƁAprintf‚Ì’¼Œã‚Åsegmentation fault‚ª‹N‚±‚éê‡‚È‚Ç‚Í‚¿‚á‚ñ‚ÆŒ‹‰Ê‚ª•\Ž¦‚³‚ê‚È‚¢B
int main(){
  int A[3];
  printf("a");
  A[3] = 1;
  return 0;
}
‚±‚ê‚ðŽÀs‚·‚é‚ƁAŒ‹‰Ê‚Í’P‚ÉSegmentation Fault‚Əo‚邾‚¯‚ŁA‚Ç‚±‚ª‚¨‚©‚µ‚¢‚©‚í‚©‚ç‚È‚¢B ‚±‚ê‚ð
  printf("a\n");
–”‚Í
  printf("a");
  fflush(stdout);
‚Æ‚·‚é‚ƁA‚¿‚á‚ñ‚Æa‚ð•\Ž¦‚µ‚½Œã‚Å—Ž‚¿‚Ä‚­‚ê‚éB

‚¿‚å‚Á‚ÆŒ«‚­printf

ƒfƒoƒbƒO‚ŁA•Ï”‚Ì–¼‘O‚Æ’l‚ð•\Ž¦‚µ‚½‚¢Žž
#define OUT(A) printf("%s = %d\n",#A, A)
‚Æ‚¢‚¤ƒ}ƒNƒ‚ð’è‹`‚µ‚Ä‚¨‚­‚ƁA
int main(){
  int i = 3;
  OUT(i);
}
‚Æ‚·‚邾‚¯‚ŁA
i = 3
‚Ý‚½‚¢‚ȏo—Í‚ª“¾‚ç‚ê‚éB‚±‚ê‚Í%d‚©‚番‚©‚é‚悤‚ɐ®”‚É‚µ‚©Žg‚¦‚È‚¢‚¯‚ǁAC++Žg‚Á‚Ä‚é‚È‚ç
#include<iostream>
#define OUT(A) std::cout << #A << '='<<A << std::endl;
int main(){
  int i = 3;
  OUT(i);
}
‚Æ‚·‚é‚ƁAint‚Å‚àdouble‚Å‚àstring‚Å‚àŽg‚¦‚Ü‚·B

assert“ü‚ê‚Ä

—Ⴆ‚΃vƒƒOƒ‰ƒ€’†‚ŁAu‚±‚±‚Íx‚ª0‚ɂ͂Ȃ肦‚È‚¢A‚È‚Á‚½‚ç‚â‚΂¢v ‚ÆŽv‚Á‚½‚çA–À‚킸‰º‚̈ês‚ð‘‚«‚Ü‚µ‚傤B
#include <assert.h> ‚±‚ê‚͐擪‚ɏ‘‚­

...
  assert(x != 0);
‚±‚¤‚·‚é‚ƁA‚à‚µx‚ª0‚É‚È‚Á‚½‚Æ‚«‚É‚¿‚傤‚Ç‚»‚±‚Å—Ž‚¿‚Ä‚­‚ê‚Ü‚·B ŽŸ‚Ìgdb‚Æ‘g‚ݍ‡‚킹‚é‚ƁAƒfƒoƒbƒO‚Ì‹­‚¢–¡•û‚É‚È‚è‚Ü‚·B

gdbŽg‚¨‚¤

GNU‚̃fƒoƒbƒKEgdb‚ÌŽg‚¢•ûBŠÈ’P‚ɁB emacs‚ªŽg‚¦‚él‚È‚çAM-x gdb‚Æ‚µ‚Äemacsã‚ÅŽg‚¤‚Ì‚ª‚¨Š©‚ß‚Å‚·B
‚Ü‚¸A-g‚ð•t‚¯‚ăRƒ“ƒpƒCƒ‹B
$ gcc test.c -g -o test
‚ŁAgdb‚ɐH‚킹‚éB
$ gdb test
(gdb)
‚±‚±‚ŁA?‚Ƒł‚Ǝg‚¦‚éƒRƒ}ƒ“ƒh‚̈ꗗ‚ªo‚éB
‚Æ‚è‚ ‚¦‚¸’m‚Á‚Ä‚¨‚­‚ׂ«‚Ȃ̂́A ‚ ‚Ƃ́AŠÖ”ŒÄ‚яo‚µŠÖŒWB –Y‚ê‚¿‚á‚¢‚¯‚È‚¢‚Ì‚ª ‚¿‚å‚Á‚ÆŽg—p—á‚ðB
#include <stdio.h>

void init(int *A, int size){
  int i;
  for(i = 0; i < size; i++) 
    A[i] = i * i;
}

void print(int *A, int size){
  int i;
  for(i = 0; i < size; i++) 
    printf("A[%d] = %d\n", i, A[i]);
}


int main(void){
  int i;
  int size = 4;
  int A[4];
  
  init(A, size);
  A[1000] = 10;
  print(A, size);
}
ŽÀs‚µ‚½‚çA‘½•ªA[1000] = 10;‚̍s‚Å—Ž‚¿‚Ü‚·B ‚»‚±‚Å‚±‚ê‚ðgdb‚ÅŽÀsB
$ gdb test
(gdb) run (‚Æ‚è‚ ‚¦‚¸ŽÀs)

Program received signal SIGSEGV, Segmentation fault.
main () at test.c:22
(gdb) where (¡‚Ç‚±‚É‚¢‚é‚©‚ð•\Ž¦)
#0  main () at test.c:22

(gdb) list (¡‚¢‚é‚ ‚½‚è‚̃\[ƒX‚ð•\Ž¦)
21        init(A, size);
22        A[1000] = 10;
23        print(A, size);

(gdb) print A[0] (A[0]‚Ì’†g‚ð•\Ž¦)
$1 = 0
(gdb) call print(A, size) (print‚Á‚Ċ֐”‚ðŒÄ‚ñ‚Å‚Ý‚é)
A[0] = 0
A[1] = 1
A[2] = 4
A[3] = 9
(gdb) 
‚±‚ñ‚ÈŠ´‚¶‚ŁAA•Ï”’†g‚ðŠÈ’P‚É‚Ì‚¼‚¯‚éB
‚»‚ê‚Æ‚©AŽÀs‘O‚Ébreak‚ðŽw’肵‚Ä‚¨‚­‚ƁASegmentation faultˆÈŠO‚Å‚à“r’†‚ÅŽ~‚߂邱‚Æ‚ª‚Å‚«‚éB
‚³‚Á‚«‚Æ“¯‚¶ƒ\[ƒX‚Å
(gdb) break init
‚Æ‚·‚é‚ƁAinit()‚É“ü‚Á‚½‚Æ‚±‚ÅŽ~‚Ü‚é‚©‚çA‚»‚±‚©‚çstep‚ňês‚¸‚i‚ß‚½‚è‚Å‚«‚éB

ƒRƒ“ƒpƒCƒ‹‚Í-Wall‚ð•t‚¯‚悤

return–Y‚ê‚É‚²’ˆÓB
ŽŸ‚̃vƒƒOƒ‰ƒ€‚́AƒRƒ“ƒpƒCƒ‹‚ð’Ê‚Á‚Ä‚µ‚Ü‚¢‚Ü‚·B(gcc version 2.95.3 20010315 (release))
#include<stdio.h>
typedef struct kei_{
  int i;
} kei;

kei *new(){
  kei *k;
  k = (kei *)malloc(sizeof(kei));
  k->i = 23;
/* ‚±‚±‚Éreturn k‚ª‚È‚¢ */
}

int main(){
  kei *k;
  k = new();
  printf("%d\n", k->i);
}
‚±‚ê‚ðŽÀs‚·‚é‚ƁA–l‚̊‹«‚Å‚Í23‚Æ•\Ž¦‚³‚ê‚Ü‚µ‚½‚ªAƒRƒ“ƒpƒCƒ‹ƒIƒvƒVƒ‡ƒ“‚ð-O3‚É•Ï‚¦‚é‚Æ“®‚©‚È‚­‚È‚è‚Ü‚µ‚½B ‚±‚¤‚¢‚¤‚½‚¿‚̈«‚¢ƒoƒO‚ð–h‚®‚ɂ́A
% gcc -g -Wall test.c
‚Æ‚µ‚ăRƒ“ƒpƒCƒ‹‚·‚é‚ƁA
warning: control reaches end of non-void function
‚ÆŒx‚ðo‚µ‚Ä‚­‚ê‚Ü‚·B

segmentation fault‚µ‚½‚ç-lefence

–l‚Ý‚½‚¢‚ÉŒoŒ±•s‘«&&’ˆÓ—ÍŽU–Ÿ‚ȃvƒƒOƒ‰ƒ}‚́A•Ï‚ȔԒn‚ɏ‘‚«‚±‚ñ‚¶‚á‚Á‚½‚èfree()‚µ‚·‚¬‚½‚è‚Æ Segmentation faultŒn‚̃Gƒ‰[‚É”Y‚Ü‚³‚ꂪ‚¿‚Å‚·‚ªA‚»‚ê‚ð‚¿‚å‚Á‚ÆŠy‚É‚·‚é•û–@B
‚±‚¤‚¢‚¤ƒZƒOƒtƒHŒn‚̃Gƒ‰[‚Ì‚¢‚â‚炵‚¢‚Æ‚±‚ë‚́AŽÀÛ‚ɃoƒO‚Á‚½ƒR[ƒh‚ð‘‚¢‚Ä‚é•”•ª‚ł͏Ǐ󂪏o‚È‚­‚āA ‚»‚ê‚Æ—y‚©—£‚ꂽ‚Æ‚±‚Å•s³‚ȃAƒNƒZƒX‚ª‹N‚±‚Á‚Ä‚½‚è‚·‚邱‚ƁB
‚±‚̃‰ƒCƒuƒ‰ƒŠ‚Ímalloc()‚Æfree()‚ðã‘‚«‚·‚邱‚ƂŁA•Ï‚ȔԒn‚ւ̏‘‚«ž‚Ý‚âA“ñdfree()‚È‚Ç‚ð’ö“xŒŸo‚µ‚Ä‚­‚êA ƒGƒ‰[‚ª‹N‚±‚Á‚½êŠ‚Å"³‚µ‚­"—Ž‚¿‚Ä‚­‚ê‚é‚悤‚É‚È‚è‚Ü‚·B
‚Ü‚¸Aefence (Electric Fence)ƒ‰ƒCƒuƒ‰ƒŠ‚ð“ü‚ê‚Ü‚·B(debian‚âgentoo‚ɂ̓pƒbƒP[ƒW‚ª‚ ‚è‚Ü‚·)
‚ ‚Ƃ̓Rƒ“ƒpƒCƒ‹‚ÌŽž‚É
gcc test.c -lefence
‚Æ‚·‚邾‚¯‚Å‚·Bo—ˆ‚½ƒoƒCƒiƒŠ‚Í•’Ê‚ÉŽÀs‚µ‚ĉº‚³‚¢B ŽÀsŽž‚É"Electric Fence‚È‚ñ‚Æ‚©"‚Á‚ăƒbƒZ[ƒW‚ªo‚ê‚΂¿‚á‚ñ‚ƃŠƒ“ƒN‚³‚ê‚Ä‚Ü‚·B

debug ‚ÌŽž‚¾‚¯ print ‚·‚éƒ}ƒNƒ

‚±‚ñ‚ȃ}ƒNƒ‚ð‘‚¢‚Ä‚¨‚­‚Æ—Ç‚¢B
#ifdef DEBUG
#define DPRINT(s...)  fprintf(stderr, s)
#else
#define DPRINT(s...)  
#endif
ƒR[ƒh‚Ì‚Ù‚¤‚Í‚±‚ñ‚È‚Ó‚¤‚ɏ‘‚­B
DPRINT("debug message %d\n", i);
‚»‚Ì‚¤‚¦‚ŁAdebug ‚µ‚½‚¢‚Æ‚«‚Í #define DEBUG ‚·‚é‚ƁAƒƒbƒZ[ƒW‚ª•\Ž¦‚³‚ê‚éB ˆÀ’肵‚Ä‚«‚½‚çAdefine DEBUG ‚ð‚Í‚¸‚¹‚΂悢B
(gcc ‚̃IƒvƒVƒ‡ƒ“‚Å -DDEBUG ‚Æ‚·‚é‚ƁADEBUG ‚Æ‚¢‚¤ƒ}ƒNƒ•Ï”‚ª’è‹`‚³‚ê‚é‚̂ŁA‚±‚ê‚ðŽg‚Á‚Ä‚à—Ç‚¢)
ƒtƒH[ƒ}ƒbƒg‚‚«ƒfƒoƒbƒOŠÖ”B
void err_printf(const char *format, ...){
    va_list arg;
    char buf[MAX_LEN];
    va_start(arg, format);
    vsprintf(buf, format, arg);
    va_end(arg);
    fprintf(FP, buf);
}
[an error occurred while processing this directive]