くsegfaults C
-
23-08-2019 - |
質問
しているプログラムsegfaultsからのポインタを演算することもある。知っていることに、これだけ簡単にチェックイン時にをタイムリーかつ詳segfaultsさないかのいずれかできる"プレス"の入力データになってしまうためです原因になりますのでsegfault(できる)、またはできる修理で使用しないでポインタの演算が必要と非常に大量の作業、お試しできまャsegfault.なので私の質問:
1)どのように、C、チsegfault?知ってい 何か のOSを起segfaultが、何ができるので、Cのプログラムのイベントでsegfaults死が少し優雅によっ Segmentation fault
?
2)携帯型です。
んその他のプログラムについてはunportable行動できるコードチsegfault,きっかけを教えてくださいできます。私はMac OS Xでしてしまいましたが、まず私が私のプログラムの作業は多くのプラットホームとしてできるという私のオプションです。
なご心配-基本的にすべてのいの印刷よりユーザーフレンドリーになるエラーメッセージの一部無料 malloc()
ed記憶します。い企画だけを無視してすべてのsegfaultsを取得しま還ます。
解決
あなたは、シグナルハンドラを定義する必要があります。これは、関数を使用して、Unixシステム上で行われる sigaction
に。私は、Fedora 64ビットおよび32ビットの、およびSun Solaris上の同じコードでこれをやりました。
他のヒント
さて、SIGSEGVはトラップ可能であり、これはPOSIXですので、その意味では移植性があります。
Buは私はあなたがセグメンテーションフォルトを扱うのではなくセグメンテーションフォルトが発生する問題を修正したいように見えることを心配します。私はそれが障害のOS、または自分のコードであったかどうかを選ぶとしたら、私は私が選ぶだろうかを知ります。私はあなたがそれを修正し、それが再びあなたを噛むことはありませんことを確認するためのテストケースを作成し、そのバグを追い詰める勧めます。
あなたは信号のための新しいシグナルハンドラをインストールするには、関数の信号を使用することができます:
#include <signal.h>
void (*signal(int signum, void (*sighandler)(int)))(int);
次のコードのようなもの:
signal(SIGINT , clean_exit_on_sig);
signal(SIGABRT , clean_exit_on_sig);
signal(SIGILL , clean_exit_on_sig);
signal(SIGFPE , clean_exit_on_sig);
signal(SIGSEGV, clean_exit_on_sig); // <-- this one is for segmentation fault
signal(SIGTERM , clean_exit_on_sig);
void
clean_exit_on_sig(int sig_num)
{
printf ("\n Signal %d received",sig_num);
}
シグナルハンドラ内で安全な行動は制限され、非常ののです。それはたとえば、free()
とprintf()
ため、除外されます再入であることが知られていない任意のライブラリ関数を呼び出すために危険なのです。ベストプラクティスは、変数を設定して返すことですが、これは非常にあなたを助けることはありません。このようなwrite()
などのシステムコールを使用することも安全です。
それは生の直接FD、しかしbacktrace_symbols_fd()
への呼び出しが間違っている、とfprintf()
の使用によって置き換える必要があります。
write()
機能が安全であることに注意してください 私は、あなたが存在しない問題を解決しようとしていると思います。少なくとも、あなたは間違って終わりに取り組んでいます。このエラー/例外がOSによってスローされるようあなたはOSだけでを、あなたのプログラムでを引き起こした(それは、のある、のキャッチのセグメンテーションフォールトすることができませんキャッチのこと)。
私は、あなたが入力に関するあなたの戦略を再考することをお勧めしたい:なぜそれをサニタイズすることは不可能でしょうか?このCのSTDLIBが適切な機能を持っているために行うことが最も重要なのは、サイズのチェックです。そして、もちろん、あなたは、コンテンツに関する有効な入力をチェックする必要があると思います。はい、これはおそらく多くの作業になりますが、それは堅牢なプログラムを書くための唯一の方法です。
編集の私はCの専門家の多くはないんだけど、でも、セグメンテーションフォールトがシグナルハンドラによって処理することができることを知りませんでした。それでも、私はそれが上記の理由のために行くための正しい方法ではないと思います。
あなたはSIGSEGVハンドラを提供する必要があります、これはかなりまともに見えます。に
信号の取り扱いが(相対的)携帯広unixマシン(macとlinuxで共通)。の大きな違いの例外の詳細に渡される引数として与えた場合、その信号の取り扱います。Sorrtyができるので,それをバ#ifdefs、印刷したい場合よりリーズナブルなエラーメッセージなどについては、によるアドレスの誤った)...
ok、こちらのコードフラグメントを始めましょう:
#include <signal.h>
/* reached when a segv occurrs */
void
SEGVFunction( SIGARGS )
{
...
}
...
main(...) {
signal(SIGSEGV, SEGVFunction); /* tell the OS, where to go in case... */
...
... do your work ...
}
あなたの仕事は:
- 確認SIGARGSはOSに依存するので、ものを使うifdef)
- 参照を抽出しよう断層のアドレスおよびpcからの情報sigArgs
- 印刷の合理的なメッセージ
- 口
理論上は、あなたのパッチのpcの信号ハンドラを降の断層運動指導)を進めています。しかし、一般的な信号ハンドラはexit()またはlongjmp()などの保存場所の主なものです。
について
ここで)(SIGSEGVをキャッチとglibcのバックトレースを使用してスタックトレースを印刷する方法の例があります:
どのようにするとき、私のスタックトレースを生成するにはC ++アプリがクラッシュする
あなたはセグメンテーションフォルトをキャッチし、クリーンアップが、警告するこれを使用することができます:あなたは、特に、シグナルハンドラ内でのmalloc()など作るの呼び出しを伴うものをあまりにも多くのものをやってはいけません。 malloc関数内からmalloc関数の呼び出しがあり、安全な信号されていない呼び出しの多くがあり、そしてあなたが作る場合、あなたは足で自分自身を撮影し終わることができ、言います。