私は Windows を使用しており、MinGW でビルドされた実行可能ファイルで GDB を実行しています。プログラムに無限ループがあります。Ctrl+を押して見つけたいC。実行すると、プログラムと GDB の両方が終了します。この件に関するすべてのヘルプは、私が Linux を使用していることを前提としているようです。
8 に答える
これは、GDB がGUI (非コンソール) プログラムのCtrl+イベントを適切に処理しないためです。C
GDB Ctrl-C 割り込みの回避策で回避策を見つけることができます。
更新: mingw.org ドメインの有効期限が切れたため、Web アーカイブから救出されたコードは次のとおりです。
GDB によってデバッグされているプログラムを Ctrl-C で中断しようとして失敗した場合、この小さなプログラムを使用すると、別のセッションからブレークを発行できます。デバッグ中のプロセスの Windows pid を渡して実行するだけで、GDB が制御を取り戻します。[コンパイルするには、使用
gcc -o debugbreak -mno-cygwin -mthreads debugbreak.c
]
/* BEGIN debugbreak.c */
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0501
#endif
#if _WIN32_WINNT < 0x0501
#error Must target Windows NT 5.0.1 or later for DebugBreakProcess
#endif
#include <Windows.h>
#include <stddef.h>
#include <stdlib.h>
/* Compile with this line:
gcc -o debugbreak -mno-cygwin -mthreads debugbreak.c
*/
static char errbuffer[256];
static const char *geterrstr(DWORD errcode)
{
size_t skip = 0;
DWORD chars;
chars = FormatMessage(
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, errcode, 0, errbuffer, sizeof(errbuffer)-1, 0);
errbuffer[sizeof(errbuffer)-1] = 0;
if (chars) {
while (errbuffer[chars-1] == '\r' || errbuffer[chars-1] == '\n') {
errbuffer[--chars] = 0;
}
}
if (chars && errbuffer[chars-1] == '.') errbuffer[--chars] = 0;
if (chars >= 2 && errbuffer[0] == '%' && errbuffer[1] >= '0'
&& errbuffer[1] <= '9')
{
skip = 2;
while (chars > skip && errbuffer[skip] == ' ') ++skip;
if (chars >= skip+2 && errbuffer[skip] == 'i'
&& errbuffer[skip+1] == 's')
{
skip += 2;
while (chars > skip && errbuffer[skip] == ' ') ++skip;
}
}
if (chars > skip && errbuffer[skip] >= 'A' && errbuffer[skip] <= 'Z') {
errbuffer[skip] += 'a' - 'A';
}
return errbuffer+skip;
}
int main(int argc, char *argv[])
{
HANDLE proc;
unsigned proc_id = 0;
BOOL break_result;
if (argc != 2) {
printf("Usage: debugbreak process_id_number\n");
return 1;
}
proc_id = (unsigned) strtol(argv[1], NULL, 0);
if (proc_id == 0) {
printf("Invalid process id %u\n", proc_id);
return 1;
}
proc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, (DWORD)proc_id);
if (proc == NULL) {
DWORD lastError = GetLastError();
printf("Failed to open process %u\n", proc_id);
printf("Error code is %lu (%s)\n", (unsigned long)lastError,
geterrstr(lastError));
return 1;
}
break_result = DebugBreakProcess(proc);
if (!break_result) {
DWORD lastError = GetLastError();
printf("Failed to debug break process %u\n", proc_id);
printf("Error code is %lu (%s)\n", (unsigned long)lastError,
geterrstr(lastError));
CloseHandle(proc);
return 1;
}
printf("DebugBreak sent successfully to process id %u\n", proc_id);
CloseHandle(proc);
return 0;
}
/* END debugbreak.c */
コードを cygwin メーリング リストhttp://cygwin.com/ml/cygwin/2006-06/msg00321.htmlに投稿してくれた Kyle McKay に感謝します。
どの「シェル」を使用していますか? MSYS「rxvt」シェルを使用する場合、動作は説明どおりです。Ctrl-C は、通常の Windows コマンド プロンプトから実行している場合にのみ機能します。
私はちょうど同じ問題にぶつかりました。
ウィキの回避策はdebugbreak
、デバッグされたプロセスの pid で実行することですが、ps
この pid は表示されず、gdb の pid のみが表示されます。もしかしたら他に入手方法があるかもしれません。
しかし、もっと簡単な回避策があります。プログラムを通常どおり (gdb ではなく) 開始し、pid をチェックps
して、この pid を 2 番目の引数として gdb を開始します。gdb がアタッチされるとプロセスが停止し、バックトレースを出力できます。
毎回機能するソリューションは次のとおりです。
GDB の開始時に、この正規表現を使用して下位プロセス ID を取得します。
"\[New Thread (\d+)\."
次に使用します。
hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, PID);
DebugBreakProcess(hProcess);
CloseHandle(hProcess);
次の GDB 初期化スクリプトを見てください。Windows 7 以降で MinGW を使用するには、これが必要です。
# =====================================
# GDB preload initialization commands
# =====================================
# Set Unicode Charset
#set target-charset UCS-2
#set host-charset UCS-2
#set charset UCS-2
#set target-wide-charset UCS-2
# Set UTF-8 Charset
set target-charset UTF-8
set host-charset UTF-8
set charset UTF-8
set target-wide-charset UTF-8
# Request async target mode
set target-async 1
# Do not complain about pending breakpoints
set breakpoint pending on
# Enable All-Stop for all Threads
set non-stop off
# Do not ask for confirmations
set confirm off
# Do not create new console for output/logging
set new-console off
# Turn-off paggination to allow integration with IDE
set pagination off
# Call Stack files (and anywhere else) should be absolute path
set filename-display absolute
# Enable Pretty Print in GDB Panel
set print pretty on
# Enable notification of completion for asynchronous execution commands.
set exec-done-display on
# Show Addresses in objects, required for integration with IDE
set print address on
# Enable Pretty Print for Arrays
set print array on
# Flatten objects, required for integration with IDE
set print object off
# Include static members, required for integration with IDE
set print static-members on
# Show demangled vtable, required for integration with IDE
set print vtbl off
set print demangle on
set demangle-style gnu-v3
# Print full eight-bit characters, required for integration with IDE
set print sevenbit-strings off
# Set path for obj files
path $(TARGET_ROOT)/obj
# Load gdb scripts for STL (string, vector, map, etc.)
source $(PATH_SDK_DEBUGGER)/stl-views-1.0.3.gdb
# List of source code files
dir $(PATH_SDK_COMMON)
dir $(PATH_SDK_FRAMEWORKS)
dir $(PATH_SDK_INCLUDES)
dir $(PROJECT_PATHS.NATIVE_COMMON)
# Load the binary
file $(TARGET_OUTPUT)
無限ループを見つけるには、無限に繰り返されるシーケンスに到達するまで実行をステップ実行してみてください。
よくわかりませんが、Ctrl-Cは実行を停止するだけで、gdb自体は停止しないと思います...
割り込み信号の処理方法を制御するために使用できる「handle」コマンドがあると思います。