Comment une langue activée par la macro continue-t-elle à suivre le code source du débogage?

StackOverflow https://stackoverflow.com/questions/3214603

Question

C'est une question plus théorique sur les macros (je pense).Je sais que les macros prennent le code source et produisent un code d'objet sans l'évaluer, ce qui permet aux programmeurs de créer des structures syntaxiques plus polyvalentes.Si je devais classer ces deux systèmes macro, je dirais qu'il y avait le "style C" macro et la macro "style LISP".

Il semble que les macros de débogage puissent être un peu difficiles, car au moment de l'exécution, le code qui fonctionne réellement diffère de la source.

Comment le débogueur continue-t-il de suivre l'exécution du programme en termes de code source prétraité?Existe-t-il un "mode de débogage" spécial qui doit être défini pour capturer des données supplémentaires sur la macro?

en C, je peux comprendre que vous définiriez un interrupteur d'heure de compilation pour le débogage, mais comment une langue interprétée serait-elle une langue interprétée, telle que certaines formes de LISP, le faire?

s'excuser de ne pas essayer cela, mais la boîte à outils LISP nécessite plus de temps que je n'ai à dépenser pour comprendre.

Était-ce utile?

La solution

Je ne pense pas qu'il y ait une différence fondamentale dans les macros "style C" et "style LISP" dans la façon dont ils sont compilés. Les deux transforment la source avant que le compilateur ne le voit. La grande différence est que les macros de C utilisent le préprocesseur C (un langage secondaire plus faible qui est principalement pour une simple substitution de chaîne), tandis que les macros de LISP sont écrits dans Lisp elle-même (et peut donc faire n'importe quoi du tout).

(comme de côté: je n'ai pas vu de lisp non compilé depuis un moment ... certainement pas depuis le tournant du siècle. Mais si quelque chose, être interprété semblerait rendre le problème de débogage macro plus facile, pas plus difficile, puisque vous avez plus d'informations sur.)

Je suis d'accord avec Michael: Je n'ai pas vu de débogueur pour C qui gère des macros du tout. Le code qui utilise des macros se transforme avant que tout se passe. Le mode "Débogage" pour la compilation C Code C signifie généralement que cela stocke Fonctions, types, variables, noms de fichiers et tels - Je ne pense pas qu'aucun d'entre eux stocke des informations sur les macros.

  • pour les programmes de débogage qui utiliser macros , Lisp est à peu près la même chose comme c ici: votre débogueur voit le Code compilé, pas la macro application. Typiquement macros sont gardé simple et débogué indépendamment avant utilisation, pour éviter la nécessité pour cela, tout comme c.

  • pour déboguer les macros eux-mêmes , avant de partir et l'utiliser quelque part, LISP a des fonctionnalités qui rendez cela plus facile que dans C, E.G., la replique et macroexpand-1 ( Bien que dans c Il y a évidemment un moyen de macroexpand un fichier entier, pleinement, à une fois que). Tu peux voir le avant et après une macroexpansion, Droit dans votre éditeur, quand vous écrivez IT.

Je ne me souviens pas de temps que j'ai couru dans une situation où le débogage dans une définition macro elle-même aurait été utile. Soit c'est un bogue dans la définition macro, dans ce cas de macroexpand-1 isole immédiatement le problème, ou c'est un bug en dessous de cela, auquel cas les installations de débogage normales fonctionnent bien et que je ne me soucie pas qu'une macroexpansion se produise entre deux cadres de mon appel pile.

Autres conseils

dans Les développeurs LISPWorks peuvent utiliser le Stepper Tool .

lispworks fournit un pas de marche, où l'on peut parcourir tout le processus d'expansion macro .

Vous devez vraiment regarder le type de support que Raquette a pour le code de débogage avec les macros. Ce soutien a deux aspects, comme le mentionne Ken. D'une part, il y a la question des macros de débogage: en commun LISP la meilleure façon de le faire consiste à développer manuellement les formes de macro. Avec le RPC, la situation est similaire mais plus primitive - vous n'exécuteriez que le code via uniquement l'expansion du RPC et inspecter le résultat. Cependant, ces deux sont insuffisants pour des macros plus impliquées, ce qui était la motivation pour avoir un macro Debugger dans Racket - Cela vous montre les étapes de l'expansion de la syntaxe une par une, avec des indications supplémentaires sur l'interface graphique pour des éléments comme des identifiants liés, etc.

sur le côté de en utilisant les macros , la raquette a toujours été plus avancée que les autres implémentations de schéma et de LISP. L'idée est que chaque expression (comme objet syntaxique) est le code plus des données supplémentaires contenant son emplacement de source. De cette façon, lorsqu'un formulaire est une macro, le code étendu qui présente des pièces provenant de la macro aura l'emplacement de la source correct - de la définition de la macro plutôt que de son utilisation (où les formulaires ne sont pas vraiment présents). Certaines implémentations de schéma et de LISP mettront en œuvre une limitée en utilisant l'identité des sous-formes, car Dmitry-VK mentionné.

Je ne sais pas sur les macros LISP (que je suppose que je suis probablement très différent de la macros C) ou de débogage, mais de nombreux - probablement - probablement la plupart des debuggers C / C ++ ne gèrent pas le débogage des sources de la macros de préprocesseur de C / C ++.

Généralement, C / C ++ Detcricuteurs, ils n'ont pas "pas" dans la définition macro.Si une macro se développe dans plusieurs instructions, le débogueur restera généralement simplement sur la même ligne source (où la macro est invoquée) pour chaque opération de débogueur 'Step' '.

Cela peut faire déboguer les macros un peu plus douloureux que ce qu'ils pourraient autrement être - encore une autre raison de les éviter en C / C ++.Si une macro est mauvaise conduite de manière erronée de manière vraiment mystérieuse, je vais tomber en mode de montage pour le déboguer ou développer la macro (manuellement ou utiliser le commutateur du compilateur).C'est assez rare que vous deviez aller à cet extrême;Si vous écrivez des macros qui sont compliqués, vous prenez probablement la mauvaise approche.

généralement dans le débogage de niveau source a une granularité de ligne ("suivante" commande) ou une granularité de niveau d'instruction ("pas dans"). Les processeurs de macro Instrument des directives spéciales dans une source traitée permettant au compilateur de cartographier des séquences compilées des instructions de la CPU pour les lignes de code source.

Dans LISP, il n'existe aucune convention entre les macros et le compilateur pour suivre le code source pour compiler le mappage de code compilé. Il n'est donc pas toujours possible de faire une première étape du code source.

L'option évidente consiste à faire une seule étape dans le code macroexpandé. Compilateur voit déjà final, étendu, version du code et peut suivre le code source de la cartographie de code de machine.

Autre option consiste à utiliser le fait que les expressions LISP pendant la manipulation ont une identité. Si la macro est simple et que la déstructuration et le collage de code dans le modèle, certaines expressions de code élargi seront identiques (en ce qui concerne la comparaison d'éq) aux expressions qui ont été lues à partir du code source. Dans ce cas, le compilateur peut mapper certaines expressions du code développé au code source.

La réponse simple est que c'est compliqué ;-) Il y a plusieurs choses différentes qui contribuent à pouvoir déboguer un programme, et encore plus pour suivre les macros.

in C et C ++, le pré-processeur est utilisé pour développer les macros et inclure le code source réel. Les noms de fichiers originaires et les numéros de ligne sont suivis dans ce fichier source étendu à l'aide des directives #Line.

http://msdn.microsoft.com/ EN-US / Bibliothèque / B5W2CZAY (vs.80) .aspx

Lorsqu'un programme C ou C ++ est compilé avec le débogage activé, l'assembleur génère des informations supplémentaires dans le fichier d'objet qui suit des lignes de source, des noms de symboles, des descripteurs de type, etc.

http://sources.redhat.com/gdb/onlinedocs/stabs.html

Le système d'exploitation comporte des fonctions permettant à un débogueur d'attacher à un processus et de contrôler l'exécution du processus; faire une pause, une étape unique, etc.

Lorsqu'un débogueur est attaché au programme, il traduit la pile de processus et le compteur de programme sous forme symbolique en examinant la signification des adresses de programme dans les informations de débogage.

Les langages dynamiques s'exécutent généralement dans une machine virtuelle, qu'il s'agisse d'un interprète ou d'un bytecode VM. C'est le VM qui fournit des crochets pour permettre à un débogueur de contrôler le flux de programme et d'inspecter l'état du programme.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top