我在 Windows 上,在 MinGW 下构建的可执行文件上运行 GDB。该程序有一个无限循环。我想通过点击Ctrl+来找到它C。当我这样做时,程序和 GDB 都会退出。关于这个主题的所有帮助似乎都假设我在 Linux 上。
8 回答
这是因为 GDB 没有正确处理GUI(非控制台)程序的Ctrl+事件。C
您可以在Workaround for GDB Ctrl-C Interrupt中找到解决方法。
更新:鉴于 mingw.org 域已过期,以下是从 Web 存档中救出的代码:
如果您发现自己试图用 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
您使用的是哪个“外壳”?如果您使用 MSYS “rxvt” shell,则行为与您描述的差不多。Ctrl-C 仅在您从正常的 Windows 命令提示符下运行时才有效。
我刚刚遇到了同样的问题。
wiki 的解决方法是debugbreak
使用被调试进程的 pid 运行,但ps
不显示此 pid,仅显示 gdb 的 pid。也许还有另一种获取方式。
但是有更简单的解决方法。只需正常启动程序(不在 gdb 中),检查 pidps
并以此 pid 作为第二个参数启动 gdb。附加 gdb 后,进程停止,我可以打印回溯。
我有同样的问题。为我解决的问题是将 gdb 与 cmd.exe 一起使用并在 gdb 中设置以下选项。
set new-console on
现在我可以使用Ctrl+c来中断 gui 和控制台程序。
这是一个每次都有效的解决方案:
当 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)
正如Matthew Talbert 指出的那样,当在 MSYS/Cygwin 中使用使用本机 MinGW 工具链构建的 GDB 时,就会发生这种情况。使用 winpty 启动 GDB 就像一个魅力,因为它是专门为此而设计的工具。它也适用于cdb.exe
.
如果您从https://www.msys2.org/安装最新的MinGW-x64 ,那么-就可以了。CtrlC
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)
如果你在Cygwin,你需要gdb
告诉handle SIGINT
:
(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 本身......
我认为有一个“句柄”命令可以用来控制中断信号的处理方式。