あなたのコードは構文的に正確でコンパイル拡張機能を使用しているためコンパイルされます。しかし、あなたのコードには、segfault
につながるいくつかの根本的な問題があります。
まず、あなたのシグナルハンドラコード:
typedef void (*sighandler_t)(int);
sighandler_t f(int pid) {
void sigintHandler(int sig) {
printf("Process %d", pid);
}
return sigintHandler;
}
これはnot standard Cであっても、実際にコンパイルするgcc
の一部のバージョンで指定することが-ftrampolines
フラグが必要です。あなたのシグナルハンドラ関数がreturn sigintHandler;
によってf
戻り、あなたが関数ポインタを返すしているとき
sigintHandler
は、このように、nested functionです:
あなたのシグナルハンドラ関数自体を解決する必要があるいくつかの問題があります。あなたのコードで
あなたはtypedef void (*sighandler_t)(int);
を持っているので、これはvoid
戻り値の型を持つ関数を指すとあなたのsigintHandler
は次のように定義されたパラメータとしてint
を取ることができ、関数ポインタ型を定義し、正しくコンパイル。代わりに、あなたのシグナルハンドラ関数は、単にのように書くことができ
:あなたの主な機能で
void sigintHandler(int sig) {
printf("Signal %d\n", sig);
}
、次のしている:
if (signal(SIGTSTP, *f(1)) == SIG_ERR) {
// ....
}
ここでは、同様にこのことを指摘しなければならないいくつかを持っています問題。最初に、signal
関数は、最初のパラメータとしてシグナル番号(通常はsignal.h
ヘッダーで定義されたマクロ)をとり、2番目の引数としてvoid func_name(int sig)
と定義された関数へのポインタをとります。
これは、です。この関数をポインタとして渡すのではなく、と呼びます。
*f(1)
は実際にf
を呼び出し、パラメータとして1
を渡します。代わりに、あなたは次のように変更になります。
if (signal(SIGTSTP, f) == SIG_ERR) {
// ....
}
をしかしf
はなくvoid
の関数ポインタを返すように定義されているので、これは警告/エラーを発する必要があります。
#include <stdio.h>
#include <signal.h>
void sigintHandler(int sig) {
printf("Signal %d", sig);
}
int main(void) {
// ...
if (signal(SIGTSTP, sigintHandler) == SIG_ERR) {
// ...
}
// ...
return 0;
}
あなたはしかし、次のように述べています:...
は、変数の挙動を持つために
だから準拠するようにコードを変更するには、あなただけの次の操作を行うことができこれはあなたが意図している変数の性質に依存しますが、信号に基づいて可変関数であれば、次のようなことができます:
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
void sig_stop(int sig) {
printf("Process %d stop\n", getpid());
}
void sig_int(int sig) {
printf("Process %d interrupt\n", getpid());
}
int main(void) {
// ...
if (signal(SIGTSTP, sig_stop) == SIG_ERR) {
// ...
}
if (signal(SIGINT, sig_int) == SIG_ERR) {
// ...
}
// ...
return 0;
}
それともswitch
ステートメントを使用することができます
一般的にワンセグ障害をデバッグする方法上の任意のヒントが本当にいただければ幸いです!
まず、segmentation faultが何であるかを理解してください。 gdb
のようなデバッガを使用してコードをステップ実行するか、クラッシュダンプを調べて具体的にsegfault
が起きている場所を調べることができます。
希望に応じることができます。
標準Cは他の関数の中で関数を定義することをサポートしていないので、これは完全にコンパイラ依存です。なぜあなたは他の内部の関数を定義する必要がありますか?また、[GCCのドキュメント](http://gcc.gnu.org/onlinedocs/gcc/Nested-Functions.html)によると、* "包含する関数が終了した後にそのアドレスからネストされた関数を呼び出そうとすると、 * – clcto
'pid'をグローバル変数に入れることはできません(' volatile sig_atomic_t'にする必要があります)。 – HolyBlackCat
ええ、私はグローバル変数を使うことができると思います。私はかなり初心者のCプログラマであり、私は一般的に教えられている[global = bad](http://wiki.c2.com/?GlobalVariablesAreBad) –