ntdll内でgdbを使用してデバッグする場合、どこからでもブレークポイントが発生する
質問
私はいくつかのことを自動化する非常に単純なプログラムを作成しました。c++で作成し、Windowsで実行します。 Codeblocks IDE内からGDBを使用してデバッグすると、どこからともなく多くのブレークポイントが発生します。何がこの問題を引き起こしているのか分かりません。ブレークポイントはメモリの問題に関連しているようです...検出したメモリリークを修正すると、ブレークポイントの数が大幅に少なくなりました。
gdbが私に言う正確なことは:
Program received signal SIGTRAP, Trace/breakpoint trap.
In ntdll!TpWaitForAlpcCompletion () (C:\Windows\system32\ntdll.dll)
プログラム内で何度もこれを取得します。プログラムが正常に実行されているように見えて、私がやりたいことを達成したとしても、私は非常に間違ったことをしているのではないかと思います。どこを見ればいいのかわからないので、誰が問題を教えてくれますか?また、それが問題でない場合、自分で設定したブレークポイントに到達できないので、それを無効にする方法を知っていますか?
事前に感謝します!
EDIT:(GDBのwhereコマンドの出力を追加): これらの各機能が何を行うかをどこで確認できますか?
#0 0x76fefadd in ntdll!TpWaitForAlpcCompletion () from C:\Windows\system32\ntdll.dll
#1 0x0028e894 in ?? ()
#2 0x76fb272c in ntdll!RtlCreateUserStack () from C:\Windows\system32\ntdll.dll
#3 0x00657fb8 in ?? ()
#4 0x00657fb8 in ?? ()
#5 0x76f4b76a in ntdll!RtlDowncaseUnicodeChar () from C:\Windows\system32\ntdll.dll
#6 0x02070005 in ?? ()
#7 0x00000b10 in ?? ()
#8 0x0028e8dc in ?? ()
#9 0x76ff0b37 in ntdll!TpQueryPoolStackInformation () from C:\Windows\system32\ntdll.dll
#10 0x038b0000 in ?? ()
#11 0x00657fb8 in ?? ()
#12 0x76f4b76a in ntdll!RtlDowncaseUnicodeChar () from C:\Windows\system32\ntdll.dll
#13 0x6e6e9a5e in ?? ()
#14 0x038b0000 in ?? ()
#15 0x038b0000 in ?? ()
#16 0x00000000 in ?? ()
解決
質問は今ではかなり古いですが、私が行ったように検索後にここに来る人を助けるかもしれないいくつかのポイントがあります:
WinXPで開発したアプリをWin7でテストしているときに、この問題が発生しました。私の場合、これはWindows 7のメモリ管理の監視と、アプリ内の不適切なメモリ割り当ての両方に関連しています。
ストーリーを短くするために、アプリコードで、( GlobalAlloc()
を使用する代わりに)エラーによって割り当てられ、 GlobalFree()で解放されたメモリブロックcode>(Cランタイムメモリプールからのポインターを使用してシステムヒープにアクセスしたため、これは間違っています)。これにより(この場合は非常に小さい)メモリリークが発生しますが、WinXPでのテスト中はまったく気付かれず、プログラム全体が明らかに正しく実行されていました。
現在、Win7で実行されると、フォールトトレラントヒープ(FTH)はアプリのこのバグを検出します(例外の原因です):
-
同時に
OutputDebugString()
(またはDbgPrint()
)を介していくつかの情報を出力しており、シンプルな DebugView ツール、またはアプリケーションのトレース時のデバッガー。したがって、受信した信号の直前に、メッセージにそのようなものが表示されます:警告:HEAP [name_of_your.exe]:
警告:無効なアドレスがRtlFreeHeapに指定されました(006B0000、006A3698)
-
そして(アプリがデバッグされている場合)デバッガーの外部には影響しないブレークポイントを出力しますが、それ以外の場合は問題を指摘するのに役立ちます。 そのブレークポイントはGDBによってSIGTRAPシグナルとして表示されます。
この時点で、2つの選択肢があります:
- コールスタックを歩いてコード内の誤った命令を見つけようとします(残念ながら、この場合、
bt
またはwhere
gdbコマンドはどこを見るのかを十分に表示できません私のコードではヒープが誤って解放されました-誰かがntdllの代わりに開始モジュールから正しい呼び出しスタックを表示する方法を知っている場合、私に知らせてください) - FTHには、バグを回避するためにメモリ内で自動的にパッチを適用する機能があるため、続行してみてください(自動パッチは、アプリの次回の実行時に事前に発生することもあります)
Moshe Leviが述べたように、ヒープの問題時に停止しないようにするには、アプリを起動する前にGDBプロンプトで handle SIGTRAP nostop
を設定できます。
要するに:はい、メモリ管理に関連するコードに何か問題がありましたが、場合によってはクラッシュせずに実行できます。ただし、デバッグモードでは、カーネルは問題の原因を突き止めようとします。
他のヒント
うわー、Linuxプラットフォームでgdbを使用していた5年前に返送されました:)
次のコマンドを使用して、SIGTRAPを受信したときにgdbが破損するのを防ぐことができます。
handle SIGTRAP nostop
しかし、私はここでスティーブをしています、代わりにWinDbgを試してください。特にWindows用に構築されました。
WindowsのネイティブデバッガーであるWinDBGを使用することをお勧めします。これにより、特にカーネルモードに移行するシンボルのスタックトレースが向上します。
Qt Creatorでgcc / mingwを使用してこのクラッシュを経験しました。
他の問題もありました。これには、間違っていると思われる変数(6バイトのオフセット)が含まれます。 私の場合、コードに大混乱をもたらしたプラグマパックであることが判明しました。
これがあった:
#pragma pack(1)
typedef struct SomeStruct
{
... // structure
} SomeStruct;
...しかし、構造の後に1のパッキングを終了し、デフォルトのバイトアライメント/パッキングに戻るプラグマpack()呼び出しで終了しませんでした。それを修正して追加:
#pragma pack(1)
typedef struct SomeStruct
{
... // structure
} SomeStruct;
#pragma pack() // <<-- with this line the heap corruption problem was stopped