7

C で Apache モジュールを作成しました。特定の条件下では、segfault になる可能性がありますが、その理由はわかりません。この時点で、それは私のコードである可能性があり、プログラムをコンパイルしている方法である可能性があります。または、OS ライブラリのバグである可能性があります (segfault は dlopen() の呼び出し中に発生します)。

GDB と Valgrind を実行してみましたが、成功しませんでした。GDB は、無意味に見える dlopen() システム コールへのバックトレースを表示します。Valgrind では、バグは実際には消えているか、少なくとも再現不可能になっているようです。一方、これらのツールに関しては、私はまったくの初心者です。

私は実稼働品質の C プログラミングに少し慣れていません (何年も前に C を使い始めましたが、専門的に扱ったことはありません)。プログラムのデバッグのコツを学ぶための最良の方法は何ですか? 他にどのようなツールを調査する必要がありますか? 要約すると、新しいバグの課題に取り組む方法をどのように見つけますか?

編集: 明確にするために、Sydius と dmckee の意見に感謝したいと思います。私はApacheのガイドを見て、dlopen(およびdlsymとdlclose)にかなり精通しています。私のモジュールはほとんどの部分で機能します (約 3,000 行のコードで、この 1 つのセクションを有効にしない限り、問題なく機能するようです)。

これが私の元の質問の由来だと思います-次に何をすべきかわかりません。GDB と Valgrind を最大限に活用していないことはわかっています。正確なフラグでコンパイルしていない可能性があることはわかっています。しかし、私はそれ以上を理解するのに苦労しています。私がすでに知っていることを教えてくれる初心者向けガイドや、必要以上のことを教えてくれるマニュアル ページを見つけることができますが、ガイダンスはありません。

4

6 に答える 6

5

残念ながら、GNUツールは最高ではありません。私の経験では、ダイナミックリンカーが水を非常に濁しています。Apacheをモジュールと静的にリンクさせることができれば、gdbは特により確実に実行できるようになります。それがどれほど簡単かはわかりません。多くはApacheビルドシステムに依存します。

valgrindでバグを簡単に再現できないのは心配ですが、ショックではありません。

適切なフラグを使用したコンパイルに関しては、valgrindとgdbの両方で、すべてを.でコンパイルすると、はるかに優れた情報が得られます-g -O0。gccのmanページの主張gcc -g -Oが十分に良いとは思わないでください。そうではありません----Oソースコード内の変数がオプティマイザーによって削除されることさえあります。

于 2008-12-13T19:30:24.507 に答える
3

デバッグ手法は一般的に言語に依存せず、そのような「Cデバッグ」という考え方はないと確信しています。
メモリリークやコードのばかげた間違いなどの単純な問題を見つけるのに役立つさまざまなツールがたくさんあり、単純なメモリのオーバーランをキャッチすることさえできます。しかし、マルチタスク/割り込みに起因する問題のような実際に見つけるのが難しい問題の場合、dmaメモリの破損は、脳と適切に記述されたコード(このコードがデバッグされることを事前に考えて)だけです。コードをデバッグするための準備について詳しくは、こちらをご覧ください。Sydiusの投稿から、Apacheにはすでに優れたトレースメカニズムが備わっているようです。それを使用して、コードベースに類似したものを追加してください。
さらに、デバッグにおけるもう1つの重要なステップは、「想定/考えない」ことです。すべてのステップを裸の事実に基づいて行い、その仮定に基づいて次のステップを実行する前に、100%の精度ですべての仮定を証明します。仮定に基づいてデバッグを行うと、通常、間違った方向に進みます。

デイブの説明の後で編集します。

次のステップは、問題の原因となるコードの最小部分を見つけることです。特定のセクションを無効にすると、モジュールがロードされるのは悲しいことです。このセクションをできるだけ小さくし、モジュールがロードされない原因となる理想的な1行が見つかるまで、セクション内のすべてを削除/モークします。そして、あなたがこの行を見つけた後。それはあなたの脳を使い始める正確な時間になります:)これが線であることを100%確認することを忘れないでください。

于 2008-12-13T19:02:35.453 に答える
2

非常に一般的なアドバイス:

  • そのバックトレースをもう一度見てください。制御するコードのスタックフレームはありますか?もしそうなら、どの行、そしてそこで何が起こっているのですか?

  • あなたは何を知ってdlopen()いますか?マニュアルを読んでいない場合。バックトレースにコードが含まれていない場合は、Apacheコードを読み込もうとしたときに失敗している可能性があります。適切なコンパイラオプションを使用してモジュールを構築しましたか?

  • 効果的なデバッグには、環境とツールを知る必要があります。Sydiusのアドバイスはここで良いです。

  • 他のパスで立ち往生している場合は、簡単なモジュールを作成、ロード、および実行できることを確認してください。おそらく、この主題に関するほとんどすべてのドキュメントにこの例があります。


デイブの説明:初心者と専門家の間は難しい場所になる可能性があります。

他の場所では使用していない問題のあるコードでライブラリを呼び出していますか?たぶん、ローダーパスはそのリソースのためだけに台無しにされています。

それを除けば、私はアドバイスが足りません。ごめん。


NB:昨年、DavidJ.Agansの本「デバッグ」を読む機会がありました。これはソフトウェア固有ではありませんが、よく読んで、すでにかなり優れたデバッガーであっても役立ちます。

于 2008-12-13T18:25:18.600 に答える
2

dlopen() 呼び出しで失敗しているという事実は、私には少し疑わしいようです。共有オブジェクトを開こうとすると、さまざまな問題が発生する可能性があります。しかし、それらのどれもがセグフォルトを引き起こす べきではありません。

私が考えることができる 1 つの例外は、SO のライブラリ初期化の問題です。その上で、より多くの情報を得るためにできることをいくつか提案します。

  • ライブラリ パスを確認し、ロードしようとしているライブラリがこのパスにあることを確認します。(注: Apache を使用しているため、Apache を実行しているユーザーのライブラリ パスも確認する必要があると思います。(ユーザーは「nobody」だと思います。) LD_LIBRARY_PATH 環境を探していると思います。複数のバージョンのライブラリがある場合、これは非常に重要になる可能性があることにも注意してください。正しいバージョンのライブラリをロードしていることを確認してください。
  • 一般的なデバッグの原則として、問題を単純化するようにしてください。私は Apache モジュールについてほとんど知らないので、Apache を方程式から外してみます: dlopen() と、場合によっては後続の dlsym() を実行して終了する単純な C プログラムを作成してみてください。このプログラムは、トラブルシューティングやデバッグを行うためのはるかに簡単な環境を提供します。このプログラムが正常に実行される場合は、プログラム セグメント フォールトの違いを詳しく調べる必要があります。(Apache の動作の違いは何ですか?) 一方、プログラムにもセグ フォールトがある場合は、ライブラリ、プログラムのコンパイラ スイッチ、およびプログラム内のコードに潜在的な問題があると考えることができます。(または上記のすべて。)

一般的なデバッグのヒントをあまり提供できなかったかもしれませんが、ここで何かが役に立てば幸いです。

于 2008-12-13T21:57:44.770 に答える
1

valgrind のドキュメントを見てみましたが、デフォルトでは子プロセスはチェックされません。Apache があなたのモジュールを子スレッドで実行できたとしても、まったく驚かないでしょう。してみてください

valgrind --trace-children=yes ....
于 2008-12-13T19:47:45.783 に答える
1

CS 以外の学生 (つまり、電気工学、数学、物理学の学生) には、カーニガンのプログラミング講義「The Practice of Programming」をお勧めします。これは、開発を支援するいくつかの基本的な概念を提供します (テストやデバッグなど)。

すでに経験豊富なプログラマーの場合は、基本的すぎるかもしれません。それから、この禅のことわざをもう 1 つ紹介します。

私がバックアップできる1つの答え:スタックトレースをもう一度見てください。これは、デバッグによる最も関連性の高いヘルプです(特に、実行が異なるモジュール(特にあなたのものとlib / OSの境界)を横切る境界にあります)。関数の引数を調べて、それらが正常かどうかを確認します)。

于 2008-12-13T20:18:50.587 に答える