16

我在 Windows 上,在 MinGW 下构建的可执行文件上运行 GDB。该程序有一个无限循环。我想通过点击Ctrl+来找到它C。当我这样做时,程序和 GDB 都会退出。关于这个主题的所有帮助似乎都假设我在 Linux 上。

4

8 回答 8

9

这是因为 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

于 2011-03-12T18:17:41.423 回答
5

您使用的是哪个“外壳”?如果您使用 MSYS “rxvt” shell,则行为与您描述的差不多。Ctrl-C 仅在您从正常的 Windows 命令提示符下运行时才有效。

于 2009-08-13T16:58:42.357 回答
2

我刚刚遇到了同样的问题。

wiki 的解决方法是debugbreak使用被调试进程的 pid 运行,但ps不显示此 pid,仅显示 gdb 的 pid。也许还有另一种获取方式。

但是有更简单的解决方法。只需正常启动程序(不在 gdb 中),检查 pidps并以此 pid 作为第二个参数启动 gdb。附加 gdb 后,进程停止,我可以打印回溯。

于 2013-01-12T23:04:23.993 回答
2

我有同样的问题。为我解决的问题是将 gdb 与 cmd.exe 一起使用并在 gdb 中设置以下选项。

set new-console on

现在我可以使用Ctrl+c来中断 gui 和控制台程序。

于 2020-12-14T17:07:00.527 回答
1

这是一个每次都有效的解决方案:

当 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)
于 2015-02-03T01:15:33.220 回答
1

正如Matthew Talbert 指出的那样,当在 MSYS/Cygwin 中使用使用本机 MinGW 工具链构建的 GDB 时,就会发生这种情况。使用 winpty 启动 GDB 就像一个魅力,因为它是专门为此而设计的工具。它也适用于cdb.exe.

于 2017-08-25T10:19:44.043 回答
1

如果您从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)
于 2020-09-01T17:20:03.707 回答
0

要找到无限循环,您可以尝试逐步执行,直到找到无限重复的序列。

我不确定,但我认为 Ctrl-C 应该只停止执行,而不是 gdb 本身......

我认为有一个“句柄”命令可以用来控制中断信号的处理方式。

于 2009-04-02T18:49:24.270 回答