16

私は Windows を使用しており、MinGW でビルドされた実行可能ファイルで GDB を実行しています。プログラムに無限ループがあります。Ctrl+を押して見つけたいC。実行すると、プログラムと GDB の両方が終了します。この件に関するすべてのヘルプは、私が Linux を使用していることを前提としているようです。

4

8 に答える 8

9

これは、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 に感謝します。

于 2011-03-12T18:17:41.423 に答える
5

どの「シェル」を使用していますか? MSYS「rxvt」シェルを使用する場合、動作は説明どおりです。Ctrl-C は、通常の Windows コマンド プロンプトから実行している場合にのみ機能します。

于 2009-08-13T16:58:42.357 に答える
2

私はちょうど同じ問題にぶつかりました。

ウィキの回避策はdebugbreak、デバッグされたプロセスの pid で実行することですが、psこの pid は表示されず、gdb の pid のみが表示されます。もしかしたら他に入手方法があるかもしれません。

しかし、もっと簡単な回避策があります。プログラムを通常どおり (gdb ではなく) 開始し、pid をチェックpsして、この pid を 2 番目の引数として gdb を開始します。gdb がアタッチされるとプロセスが停止し、バックトレースを出力できます。

于 2013-01-12T23:04:23.993 に答える
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 に答える
0

無限ループを見つけるには、無限に繰り返されるシーケンスに到達するまで実行をステップ実行してみてください。

よくわかりませんが、Ctrl-Cは実行を停止するだけで、gdb自体は停止しないと思います...

割り込み信号の処理方法を制御するために使用できる「handle」コマンドがあると思います。

于 2009-04-02T18:49:24.270 に答える