134 votes

Rendre votre étape de langage .NET correctement dans le débogueur

Tout d'abord, je m'excuse pour la longueur de cette question.

Je suis l'auteur de IronScheme. Récemment, j'ai travaillé dur sur émettant décent informations de débogage, de sorte que je peux utiliser le "native".NET débogueur.

Tout cela a été en partie réussi, je suis en cours d'exécution dans certains problèmes de dentition.

Le premier problème est lié à l'intensification.

En raison de Régime étant une expression de la langue, tout tend à être enveloppé dans la parenthèse, à la différence de la majeure .NET languages qui semble être énoncé (ou de ligne).

Le code d'origine (Schéma) ressemble à:

(define (baz x)
  (cond
    [(null? x) 
      x]
    [(pair? x) 
      (car x)]
    [else
      (assertion-violation #f "nooo" x)]))

J'ai exprès mis chaque expression sur un retour à la ligne.

Le code émis transforme en C# (via ILSpy) ressemble à:

public static object ::baz(object x)
{
  if (x == null)
  {
    return x;
  }
  if (x is Cons)
  {
    return Builtins.Car(x);
  }
  return #.ironscheme.exceptions::assertion-violation+(
     RuntimeHelpers.False, "nooo", Builtins.List(x));
}

Comme vous pouvez le voir, assez simple.

Remarque: Si le code a été transformé en une expression conditionnelle (?:) en C#, le tout serait juste un debug étape, gardez cela à l'esprit.

Ici, IL est sortie avec la source et les numéros de ligne:

  .method public static object  '::baz'(object x) cil managed
  {
    // Code size       56 (0x38)
    .maxstack  6
    .line 15,15 : 1,2 ''
//000014: 
//000015: (define (baz x)
    IL_0000:  nop
    .line 17,17 : 6,15 ''
//000016:   (cond
//000017:     [(null? x) 
    IL_0001:  ldarg.0
    IL_0002:  brtrue     IL_0009

    .line 18,18 : 7,8 ''
//000018:       x]
    IL_0007:  ldarg.0
    IL_0008:  ret

    .line 19,19 : 6,15 ''
//000019:     [(pair? x) 
    .line 19,19 : 6,15 ''
    IL_0009:  ldarg.0
    IL_000a:  isinst [IronScheme]IronScheme.Runtime.Cons
    IL_000f:  ldnull
    IL_0010:  cgt.un
    IL_0012:  brfalse    IL_0020

    IL_0017:  ldarg.0
    .line 20,20 : 7,14 ''
//000020:       (car x)]
    IL_0018:  tail.
    IL_001a:  call object [IronScheme]IronScheme.Runtime.Builtins::Car(object)
    IL_001f:  ret

    IL_0020:  ldsfld object 
         [Microsoft.Scripting]Microsoft.Scripting.RuntimeHelpers::False
    IL_0025:  ldstr      "nooo"
    IL_002a:  ldarg.0
    IL_002b:  call object [IronScheme]IronScheme.Runtime.Builtins::List(object)
    .line 22,22 : 7,40 ''
//000021:     [else
//000022:       (assertion-violation #f "nooo" x)]))
    IL_0030:  tail.
    IL_0032:  call object [ironscheme.boot]#::
       'ironscheme.exceptions::assertion-violation+'(object,object,object)
    IL_0037:  ret
  } // end of method 'eval-core(033)'::'::baz'

Remarque: Pour empêcher le débogueur de simplement en soulignant l'ensemble de la méthode, je fais la méthode de point d'entrée à seulement 1 colonne de large.

Comme vous pouvez le voir, chaque expression correctement les cartes à une ligne.

Maintenant, le problème avec les pas à pas (testé sur VS2010, mais même problème sur VS2008):

Ce sont avec IgnoreSymbolStoreSequencePoints n'est pas appliqué.

  1. Appel baz avec null arg, il fonctionne correctement. (null? x), suivie par x.
  2. Appel baz, par Contre arg, il fonctionne correctement. (null? x) alors (paire? x) alors (car x).
  3. Appel baz avec d'autres arg, il échoue. (null? x) alors (paire? x) alors (car x) alors (affirmation de la violation ...).

Lors de l'application d' IgnoreSymbolStoreSequencePoints (comme recommandé):

  1. Appel baz avec null arg, il fonctionne correctement. (null? x), suivie par x.
  2. Appel baz, par Contre arg, il échoue. (null? x) alors (paire? x).
  3. Appel baz avec d'autres arg, il échoue. (null? x) alors (paire? x) alors (car x) alors (affirmation de la violation ...).

Je trouve aussi dans ce mode que certaines lignes (non montré ici) sont incorrectement mis en évidence, ils sont à 1.

Voici quelques idées de ce que pourrait être les causes:

  • Tailcalls confond le débogueur
  • Le chevauchement des lieux (non montré ici) confond le débogueur (il le fait très bien lors de la configuration d'un point d'arrêt)
  • ????

La deuxième, mais aussi grave, le problème est le débogueur à défaut de casser/hit points d'arrêt dans certains cas.

Le seul endroit où je peux obtenir le débogueur pour rompre correctement (et toujours), est à la méthode de point d'entrée.

La situation devient un peu mieux quand IgnoreSymbolStoreSequencePoints n'est pas appliquée.

Conclusion

Il se pourrait que le VS débogueur est tout simplement buggy :(

Références:

  1. Faire un CLR/.NET Langue Debuggable

Mise à jour 1:

Mdbg ne fonctionne pas pour la version 64 bits assemblées. De sorte que c'est. Je n'ai plus les machines 32 bits, pour faire des tests. Mise à jour: je suis sûr que c'est pas un gros problème, quelqu'un aurait-il une solution? Edit: Oui, je suis bête, il suffit de commencer mdbg en vertu de l'x64 l'invite de commande :)

Mise à jour 2:

J'ai créé une application en C#, et j'ai essayé de disséquer la ligne info.

Mes conclusions:

  • Après tout brXXX d'instructions, vous devez avoir un point de séquence (si ce n'est valable aka '#line caché", émettent un nop).
  • Avant tout brXXX instruction, émettent un "#line caché " et un nop.

Cette application n'est toutefois pas de résoudre les problèmes (seul?).

Mais l'adjonction de ce qui suit, donne le résultat souhaité :)

  • Après l' ret, émettent un "#line caché " et un nop.

C'est à l'aide de la mode où IgnoreSymbolStoreSequencePoints n'est pas appliquée. Lorsqu'il est appliqué, certaines étapes sont encore ignorés :(

Voici le IL lors de la sortie ci-dessus a été appliquée:

  .method public static object  '::baz'(object x) cil managed
  {
    // Code size       63 (0x3f)
    .maxstack  6
    .line 15,15 : 1,2 ''
    IL_0000:  nop
    .line 17,17 : 6,15 ''
    IL_0001:  ldarg.0
    .line 16707566,16707566 : 0,0 ''
    IL_0002:  nop
    IL_0003:  brtrue     IL_000c

    .line 16707566,16707566 : 0,0 ''
    IL_0008:  nop
    .line 18,18 : 7,8 ''
    IL_0009:  ldarg.0
    IL_000a:  ret

    .line 16707566,16707566 : 0,0 ''
    IL_000b:  nop
    .line 19,19 : 6,15 ''
    .line 19,19 : 6,15 ''
    IL_000c:  ldarg.0
    IL_000d:  isinst     [IronScheme]IronScheme.Runtime.Cons
    IL_0012:  ldnull
    IL_0013:  cgt.un
    .line 16707566,16707566 : 0,0 ''
    IL_0015:  nop
    IL_0016:  brfalse    IL_0026

    .line 16707566,16707566 : 0,0 ''
    IL_001b:  nop
    IL_001c:  ldarg.0
    .line 20,20 : 7,14 ''
    IL_001d:  tail.
    IL_001f:  call object [IronScheme]IronScheme.Runtime.Builtins::Car(object)
    IL_0024:  ret

    .line 16707566,16707566 : 0,0 ''
    IL_0025:  nop
    IL_0026:  ldsfld object 
      [Microsoft.Scripting]Microsoft.Scripting.RuntimeHelpers::False
    IL_002b:  ldstr      "nooo"
    IL_0030:  ldarg.0
    IL_0031:  call object [IronScheme]IronScheme.Runtime.Builtins::List(object)
    .line 22,22 : 7,40 ''
    IL_0036:  tail.
    IL_0038:  call object [ironscheme.boot]#::
      'ironscheme.exceptions::assertion-violation+'(object,object,object)
    IL_003d:  ret

    .line 16707566,16707566 : 0,0 ''
    IL_003e:  nop
  } // end of method 'eval-core(033)'::'::baz'

Mise à jour 3:

Problème avec dessus de "semi-fix". Peverify rapports d'erreurs sur toutes les méthodes en raison de l' nop après ret. Je ne comprends pas le problème. Comment peut - nop pause de vérification après un ret. C'est comme du code mort (sauf qu'il n'est PAS même code) ... eh bien, l'expérimentation continue.

Mise à jour 4:

De retour à la maison maintenant, enlevé le "invérifiable" code, en cours d'exécution sur VS2008 et les choses sont bien pires. Peut-être l'exécution de code non vérifiable pour des raisons de débogage appropriés pourrait être la réponse. Dans "libération" mode, toutes les données de sortie serait toujours vérifiables.

Mise à jour 5:

J'ai maintenant décidé de mon idée ci-dessus est la seule option viable pour l'instant. Bien que le code généré est invérifiable, j'ai encore trouvé aucune VerificationException'. Je ne sais pas quel sera l'impact sur l'utilisateur final avec ce scénario.

En bonus, ma deuxième question a également être résolus. :)

Voici une petite vidéo de démonstration de ce que j'ai. Il frappe des points d'arrêt, une bonne étape (in/out/), etc. Dans l'ensemble, l'effet désiré.

Cependant, je suis toujours pas accepter ce que la façon de le faire. Il se sentir trop hacky pour moi. Avoir une confirmation sur le vrai problème, ce serait bien.

Jour 6:

Juste eu le changement de tester le code sur VS2010, il semble y avoir quelques problèmes:

  1. Le premier appel de ne pas marcher correctement. (affirmation de la violation ...) est atteint. Dans d'autres cas, des œuvres d'amende. Certains vieux code émis inutile positions. Enlevé le code fonctionne comme prévu. :)
  2. Plus sérieusement, les points d'arrêt d'échouer sur la deuxième invocation du programme (à l'aide-mémoire de la compilation, de l'immersion de l'assemblée pour déposer semble faire des points d'arrêt encore heureux).

Ces deux cas fonctionner correctement sous VS2008. La principale différence est que, sous VS2010, l'ensemble de l'application est compilée .NET 4 et sous VS2008, compile .NET 2. Les deux cours d'exécution 64 bits.

Jour 7:

Comme mentionné, j'ai eu mdbg fonctionnant sous 64 bits. Malheureusement, c'est aussi avoir le point d'arrêt d'un problème où il ne parvient pas à percer si je exécutez à nouveau le programme (ce qui implique qu'il obtient recompilé, afin de ne pas utiliser le même montage, mais toujours en utilisant la même source).

Jour 8:

J'ai déposé un bug lors de la connexion MS site concernant le point d'arrêt de l'émission.

Mode coup de gueule

Espérons que ce n'est fixée par les états membres, à la différence des précédentes bugs que la réclamation est fixe, mais sont encore à être vu en public.

Coup de gueule de désactiver le mode

26voto

Luke Points 850

Je suis un ingénieur sur le Débogueur de Visual Studio team.

Corrigez-moi si je me trompe, mais il semble que la seule question qui reste, c'est que lors du passage de la Pdb à la .NET 4 dynamique de la compilation symbole de format de certains points d'arrêt ne sont pas vaccinés.

Nous aurait probablement besoin d'une repro exactement à diagnostiquer le problème, cependant voici quelques notes qui pourraient vous aider.

  1. VS (2008+) peut-exécuter un compte non-admin
  2. Faire tous les symboles de la charge à tous les la deuxième fois? Vous pouvez faire le test par effraction (par le biais d'exception ou de l'appel Système.De Diagnostic.Débogueur.Pause())
  3. En supposant que les symboles de la charge, est-il une repro que vous pourriez nous envoyer?
  4. La différence probable est que le format de symbole pour la dynamique du code compilé est 100% différent entre les deux .NET 2 (APB stream) et .NET 4 (IL DB je pense qu'ils ont appelé?)
  5. Le " pon de sons sur la droite. Voir les règles pour générer implicite de la séquence de points ci-dessous.
  6. Vous n'avez pas besoin d'émettre de choses sur des lignes différentes. Par défaut, contre la volonté de l'étape de "symbole-états" où, comme le compilateur écrivain, vous devez définir ce que "symbole-déclaration". Donc, si vous voulez que chaque expression doit être une activité à part dans le fichier de symboles, qui fonctionnent très bien.

L'équipe crée un implicite point de séquence basée sur les règles suivantes: 1. IL nop instructions 2. IL pile vide de points 3. L'instruction IL immédiatement à la suite d'un appel d'instruction

Si il s'avère que nous avons besoin d'une repro pour résoudre votre problème, vous pouvez déposer une connexion bug et de télécharger des fichiers en toute sécurité grâce à ce support.

Mise à jour:

Nous encourageons d'autres utilisateurs rencontrant ce problème pour essayer la Developer Preview de Dev11 de http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=27543 et commentaire avec des commentaires. (Doit cibler 4.5)

Mise à jour 2:

Leppie a vérifié la correction du travail pour lui sur la version Beta de Dev11 disponible à http://www.microsoft.com/visualstudio/11/en-us/downloads comme indiqué dans la connexion bug https://connect.microsoft.com/VisualStudio/feedback/details/684089/.

Merci,

Luc

3voto

dsrbecky Points 91

Je suis un ingénieur sur le SharpDevelop Débogueur de l'équipe :-)

Avez-vous résolu le problème?

Avez-vous essayez de déboguer dans SharpDevelop? Si il y a un bug dans .NET, je me demande si nous avons besoin de mettre en œuvre certaines de solution de contournement. Je ne suis pas au courant de ce problème.

Avez-vous essayez de déboguer dans ILSpy? Surtout sans les symboles de débogage. Il serait de débogage de code C#, mais il faudrait nous dire si les instructions IL sont bien debugable. (L'esprit que ILSpy débogueur est la bêta)

Notes rapides sur l'original IL code:

  • .ligne 19,19 : 6,15 " se produit deux fois?
  • .ligne 20,20 : 7,14 " ne démarre pas sur l'implicite point de séquence (la pile n'est pas vide). Je suis inquiet
  • .ligne 20,20 : 7,14 " inclut le code pour la voiture "x" (bon) ainsi que "#f nooon x" (mauvais?)
  • concernant le nop après ret. Qu'en est stloc, ldloc, ret? Je pense que C# utilise ce truc pour faire de ret une séquence distincte point.

David

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X