[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);
}