簡體   English   中英

如何使用gdb逐步執行宏擴展的每一行

[英]how to see step by step execution of each line of a macro expansion using gdb

我有一個宏,其定義大約有50行,並且有很多'if else'語句。 此宏def'n出現在.h文件中。 我在TUI模式下運行'gdb',但是當執行到達該宏時,代碼窗口變為空白並僅在宏代碼執行后返回。 我希望逐行執行完整的宏代碼。 請告訴我怎么做(一種方法是用代碼中的定義替換宏然后重新編譯它。我不想使用這個選項,因為我的代碼中有幾個這樣的宏)。

任何幫助將不勝感激。 期待獲得此問題的解決方案。 如果有其他方法解決此問題而不是使用預處理文件,請告訴我? 我有一個代碼,它可以運行幾百個.c和.h文件。

一種選擇是完全預處理C文件,擴展其中的所有宏,然后編譯生成的預處理文件。

例如,考慮這個簡單的C程序:

// file: prep.c
#include <stdio.h>

#define MY_BIG_MACRO \
  int i; \
  printf("integers from 0 to 9:\n"); \
  for (i = 0; i < 10; i++) \
    printf("%d ", i); \
  printf("\n");

int main(void)
{
  MY_BIG_MACRO
  return 0;
}

編譯它,保存臨時文件(包括預處理的源代碼):

gcc -Wall -O2 -g -std=c99 prep.c -o prep.exe -save-temps

這應該給你一個preprocessed版本的prep.cprep.i (為簡潔起見縮短):

# 1 "prep.c"
# 1 "C:\\MinGW\\msys\\1.0\\home\\Alex//"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "prep.c"

# 1 "c:\\mingw\\bin\\../lib/gcc/mingw32/4.6.2/../../../../include/stdio.h" 1 3

...

int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) vswscanf (const wchar_t * __restrict__,
         const wchar_t * __restrict__, __gnuc_va_list);
# 3 "prep.c" 2
# 11 "prep.c"
int main(void)
{
  int i; printf("integers from 0 to 9:\n"); for (i = 0; i < 10; i++) printf("%d ", i); printf("\n");
  return 0;
}

現在你想擺脫#-lines。 無論如何,如果將它們留在中,它們將影響調試信息。 令人驚訝的是,這意味着宏不會在gdb出現擴展。

值得慶幸的是, grep可以提供幫助(我不是grep專業人員,所以請檢查params是否正確,但它們似乎適用於使用MinGW x86的Windows):

grep ^[^\#].*$ prep.i > prepi.c

這將為您提供prep.i中的prepi.c的剝離版本:

typedef unsigned int size_t;
typedef short unsigned int wchar_t;
typedef short unsigned int wint_t;

...

int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) vswscanf (const wchar_t * __restrict__,
         const wchar_t * __restrict__, __gnuc_va_list);
int main(void)
{
  int i; printf("integers from 0 to 9:\n"); for (i = 0; i < 10; i++) printf("%d ", i); printf("\n");
  return 0;
}

現在你可以編譯它:

gcc -Wall -O2 -g -std=c99 prepi.c -o prepi.exe

並在gdb運行它:

gdb prepi.exe

發出以下命令:

b main
r
l

這將執行app直到main()並列出與到達的斷點相關的源代碼:

(gdb) b main
Breakpoint 1 at 0x40643f: file prepi.c, line 184.
(gdb) r
Starting program: C:\MinGW\msys\1.0\home\Alex\prepi.exe
[New Thread 7340.0x20c4]

Breakpoint 1, main () at prepi.c:184
184       int i; printf("integers from 0 to 9:\n"); for (i = 0; i < 10; i++) pri
ntf("%d ", i); printf("\n");
(gdb) l
179              const wchar_t * __restrict__, __gnuc_va_list);
180     int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) vswscanf (c
onst wchar_t * __restrict__,
181              const wchar_t * __restrict__, __gnuc_va_list);
182     int main(void)
183     {
184       int i; printf("integers from 0 to 9:\n"); for (i = 0; i < 10; i++) pri
ntf("%d ", i); printf("\n");
185       return 0;
186     }
(gdb)

如您所見,宏體現在處於普通視圖中。

這里的一個小問題是多行宏(繼續用\\ )擴展為一行。 我還沒有找到將它們擴展為多行的選項,但您可以手動執行此操作。

“人們不只是step成宏。”

你還有幾個選擇:

  1. 使用預處理器,如@WhozCraig推薦的那樣。
  2. 為了減少代碼膨脹,將宏轉換為函數並重新編譯。
  3. 如果您絕對不想重新編譯並且您對匯編代碼感到滿意,則可以使用stepi執行宏一台機器指令。

如果以上所有方法都不起作用,那么你應該回到在大宏中使用printf/fprintf

我不得不處理300線MACRO,深入圖書館。 這比手工編譯和處理后處理文件更容易。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM