我在Windows上,运行在MinGW下编译的可执行文件上的GDB。该程序有一个无限循环。我想通过按下Ctrl + C来找到它。但是这样做会导致程序和GDB同时退出。所有有关此主题的帮助似乎都默认我在Linux上。
这是因为 GDB 不能正确处理 GUI(非控制台)程序的 Ctrl + C 事件。
你可以在 Workaround for GDB Ctrl-C Interrupt 中找到解决方法。
更新: 鉴于 mingw.org 域名已过期,以下代码通过 Web Archive 恢复:
如果您正在尝试使用 Ctrl-C 打断被 GDB 调试的程序并失败,则此小程序将允许您从另一个会话发出中断。只需运行它并传递正在调试的进程的 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 */
感谢 Kyle McKay 在cygwin邮件列表上发布的代码http://cygwin.com/ml/cygwin/2006-06/msg00321.html
您使用的是哪种“shell”?如果您使用的是MSYS“rxvt” shell,则行为与您描述的基本相同。只有在从普通的Windows命令提示符中运行时,Ctrl-C才有效。
我也遇到过同样的问题。解决方法是使用cmd.exe和gdb,并在gdb中设置如下选项。
set new-console on
debugbreak
,但是ps
只显示gdb的pid,可能还有其他获取pid的方法。ps
中检查pid并将其作为第二个参数启动gdb。
当gdb附加到进程时,进程会停止,然后我可以打印回溯信息。bt
命令来显示堆栈信息。我想对真正了解GDB的人来说,这是非常显而易见的。 - Mike Dunlavey"\[New Thread (\d+)\."
hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, PID);
DebugBreakProcess(hProcess);
CloseHandle(hProcess);
# =====================================
# 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)
正如Matthew Talbert提出的那样,当使用使用本地MinGW工具链构建的GDB在MSYS/Cygwin中使用时会出现这种情况。使用winpty启动GDB非常有效,因为它是专门为此设计的工具。它也适用于cdb.exe
。
c:\test>gdb a.exe
GNU gdb (GDB) 7.11.1
. . .
Reading symbols from a.exe...done.
(gdb) r
Starting program: c:\test\a.exe
<Ctrl>-<C>
Thread 5 received signal SIGINT, Interrupt.
[Switching to Thread 17312.0x5614]
0x00007ff97e75d7e3 in TlsGetValue () from C:\WINDOWS\System32\KernelBase.dll
(gdb)
(gdb) handle SIGINT
SIGINT is used by the debugger.
Are you sure you want to change it? (y or n) y
Signal Stop Print Pass to program Description
SIGINT Yes Yes No Interrupt
(gdb)
要找到无限循环,您可以尝试逐步执行,直到您到达一个无限重复的序列。
我不确定,但我认为Ctrl-C只应该停止执行,而不是gdb本身...
我认为有一个“handle”命令,您可以使用它来控制如何处理中断信号。
cmd.exe
的控制台确实有所帮助:我按下Ctrl+C,GDB的行为就像在Linux上一样。因此,这里链接的解决方法并不是那么有用。 - Ruslan