[an error occurred while processing this directive]
[an error occurred while processing this directive]int main(){ int A[3]; printf("a"); A[3] = 1; return 0; }これを実行すると、結果は単にSegmentation Faultと出るだけで、どこがおかしいかわからない。 これを
printf("a\n");又は
printf("a"); fflush(stdout);とすると、ちゃんとaを表示した後で落ちてくれる。
#define OUT(A) printf("%s = %d\n",#A, A)というマクロを定義しておくと、
int main(){ int i = 3; OUT(i); }とするだけで、
i = 3みたいな出力が得られる。これは%dから分かるように整数にしか使えないけど、C++使ってるなら
#include<iostream> #define OUT(A) std::cout << #A << '='<<A << std::endl; int main(){ int i = 3; OUT(i); }とすると、intでもdoubleでもstringでも使えます。
#include <assert.h> これは先頭に書く
...
assert(x != 0);
こうすると、もしxが0になったときにちょうどそこで落ちてくれます。
次のgdbと組み合わせると、デバッグの強い味方になります。
$ gcc test.c -g -o testで、gdbに食わせる。
$ gdb test (gdb)ここで、?と打つと使えるコマンドの一覧が出る。
#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); }実行したら、多分A[1000] = 10;の行で落ちます。 そこでこれをgdbで実行。
$ gdb test (gdb) run (とりあえず実行) Program received signal SIGSEGV, Segmentation fault. main () at test.c:22 (gdb) where (今どこにいるかを表示) #0 main () at test.c:22 (gdb) list (今いるあたりのソースを表示) 21 init(A, size); 22 A[1000] = 10; 23 print(A, size); (gdb) print A[0] (A[0]の中身を表示) $1 = 0 (gdb) call print(A, size) (printって関数を呼んでみる) A[0] = 0 A[1] = 1 A[2] = 4 A[3] = 9 (gdb)こんな感じで、、変数中身を簡単にのぞける。
(gdb) break init
とすると、init()に入ったとこで止まるから、そこからstepで一行ずつ進めたりできる。
#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); }これを実行すると、僕の環境では23と表示されましたが、コンパイルオプションを-O3に変えると動かなくなりました。 こういうたちの悪いバグを防ぐには、
% gcc -g -Wall test.cとしてコンパイルすると、
warning: control reaches end of non-void functionと警告を出してくれます。
gcc test.c -lefenceとするだけです。出来たバイナリは普通に実行して下さい。 実行時に"Electric Fenceなんとか"ってメッセージが出ればちゃんとリンクされてます。
#ifdef DEBUG #define DPRINT(s...) fprintf(stderr, s) #else #define DPRINT(s...) #endifコードのほうはこんなふうに書く。
DPRINT("debug message %d\n", i);そのうえで、debug したいときは #define DEBUG すると、メッセージが表示される。 安定してきたら、define DEBUG をはずせばよい。
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); }