Ich habe ein Makro, dessen Definition etwa 50 Zeilen umfasst und viele „Wenn-sonst“-Anweisungen enthält. Diese Makrodefinition erscheint in einer .h-Datei. Ich verwende „gdb im TUI-Modus“, aber wenn die Ausführung dieses Makro erreicht, wird das Codefenster leer und kehrt erst zurück, nachdem der Makrocode ausgeführt wurde. Ich möchte die zeilenweise Ausführung des vollständigen Makrocodes sehen. Bitte lassen Sie mich wissen, wie das geht (eine Möglichkeit besteht darin, das Makro durch seine Definition im Code zu ersetzen und es dann neu zu kompilieren. Ich möchte diese Option nicht verwenden, da mein Code mehrere solcher Makros enthält).
Jede Hilfe wird sehr geschätzt. Ich freue mich darauf, die Lösung für dieses Problem zu finden. Bitte lassen Sie mich wissen, ob es für dieses Problem eine andere Möglichkeit als die Verwendung einer vorverarbeiteten Datei gibt? Ich habe einen Code, der mehrere hundert .c- und .h-Dateien umfasst.
Eine Möglichkeit besteht darin, Ihre C-Datei vollständig vorzuverarbeiten, alle darin enthaltenen Makros zu erweitern und dann die resultierende vorverarbeitete Datei zu kompilieren.
Betrachten Sie zum Beispiel dieses einfache C-Programm:
// 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;
}
Kompilieren Sie es und speichern Sie die temporären Dateien (einschließlich des vorverarbeiteten Quellcodes):
gcc -Wall -O2 -g -std=c99 prep.c -o prep.exe -save-temps
Dadurch sollten Sie eine vorverarbeitete Version von erhalten prep.c
, prep.i
(der Kürze halber gekürzt):
# 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;
}
Jetzt möchten Sie die #-Zeilen loswerden. Wenn sie drin bleiben, wirken sie sich auf die eine oder andere Weise auf die Debug-Informationen aus. Überraschenderweise bedeutet dies, dass das Makro nicht erweitert angezeigt wird gdb
.
Gott sei Dank, grep
kann helfen (ich bin kein Grep-Profi, also prüfen Sie, ob die Parameter korrekt sind, aber sie scheinen bei mir unter Windows mit MinGW x86 zu funktionieren):
grep ^[^\#].*$ prep.i > prepi.c
Dadurch erhalten Sie eine abgespeckte Version von prep.i
In 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;
}
Jetzt können Sie es kompilieren:
gcc -Wall -O2 -g -std=c99 prepi.c -o prepi.exe
Und lassen Sie es einlaufen gdb
:
gdb prepi.exe
Geben Sie die folgenden Befehle ein:
b main
r
l
Dadurch wird die App ausgeführt, bis main()
und listen Sie den Quellcode auf, der sich auf den erreichten Haltepunkt bezieht:
(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)
Wie Sie sehen können, befindet sich der Makrokörper jetzt in der einfachen Ansicht.
Ein kleines Problem hierbei ist, dass mehrzeilige Makros (die Fortsetzung mit \
) werden zu einer einzigen Zeile erweitert. Ich habe keine Option gefunden, sie in mehrere Zeilen zu erweitern, aber Sie können das manuell tun.
“Man macht nicht einfach step
in Makros.
Sie haben noch einige Möglichkeiten:
- Verwenden Sie den Präprozessor, wie von @WhozCraig empfohlen.
- Um den Code etwas weniger aufzublähen, konvertieren Sie Ihre Makros in Funktionen und kompilieren Sie sie erneut.
- Wenn Sie auf keinen Fall neu kompilieren möchten und mit dem Assembler-Code vertraut sind, können Sie ihn verwenden
stepi
um Ihr Makro jeweils einzeln auszuführen.
Wenn all das nicht funktioniert, sollten Sie es wirklich wieder verwenden printf/fprintf
innerhalb Ihres großen Makros.
Ich musste mich mit einem 300-Zeilen-MAKRO auseinandersetzen, das tief in der Bibliothek vergraben war. Dies war einfacher als das Kompilieren von Hand und der Umgang mit nachbearbeiteten Dateien.