我是GDB的初學者,正確說Linux的環境其實都還不熟, 但公司整個開發環境都是以linux為base, 所以必須要熟析上面的開發工具, GDB就是其中一個, 因此我自己先在Windows系統上架設了仿Linux bash的環境也就是(MinGW + MSYS), 想要先在windows下執行程式並用GDB去debug trace, 藉此瞭解程式的運作和workflow, 但因為該程式是multi-thread的, 但我又不清楚整個運作流程, 所以想要先讓程式run一段時間後在中途中斷, 觀察一下thread的create情況, 但每次當我想要這樣做時(先用GDB 載入要trace的程式, 然後讓它執行一段時間) , 按下Ctrl+C想藉此中斷該程式, 每次這樣做都會讓整個程式停止並跳出執行, 根本無法順利的中途中斷它然後繼續使用GDB commands來一步一步trace. 這是前情提要
後來在網路上(經由Orson的幫忙搜尋) 找到了這個討論串GDB Ctrl-C Interrupt Fails WORKAROUND(
http://cygwin.com/ml/cygwin/2006-06/msg00321.html), 自己動手try了一下, 確實可行耶, 雖然它是for cygwin的, 但在MinGW+MSYS下也是可以運作的, 差別是我compile該程式的方法省略掉了"-mno-cygwin", 也就是compile語法為
gcc -o debugbreak.exe -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
#include
#include
/* 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 */