web-dev-qa-db-fra.com

Comment appeler des méthodes ou exécuter du code dans le débogueur LLDB?

Je sais que je peux taper print someFloatVariable lorsque je définit un point d'arrêt ou po [self someIvarHoldingAnObject], mais je ne peux pas faire de choses utiles comme:

[self setAlpha:1];

Puis il crache:

erreur: "[self" n'est pas une commande valide.

Chose bizarre, je peux appeler po [self someIvarHoldingAnObject] et il imprimera sa description.

Je crois avoir vu une vidéo il y a un an où quelqu'un a montré comment exécuter du code via la console lors de l'exécution, et si je ne me trompe pas, ce type a également fourni des arguments et assigné des objets aux pointeurs. Comment faire ça?

60
Proud Member

La référence canonique pour les commandes gdb v. Lldb est http://lldb.llvm.org/lldb-gdb.html

Vous souhaitez utiliser la commande expr qui évalue une expression. C'est l'une des commandes lldb qui prend "l'entrée brute" en plus des arguments, donc vous avez souvent besoin d'un "-" pour indiquer où les arguments (à expr) se terminent et la ou les commandes commencent. par exemple.

(lldb) expr -- [self setAlpha:1]

Il y a un raccourci, "p", qui fait le - pour vous (mais ne permet aucun argument), par ex.

(lldb) p [self setAlpha:1]

Si la ou les fonctions que vous appelez ne font pas partie de votre programme, vous devrez souvent déclarer explicitement leur type de retour pour que lldb sache comment les appeler. par exemple.

(lldb) p printf("hi\n")
error: 'printf' has unknown return type; cast the call to its declared return type
error: 1 errors parsing expression
(lldb) p (int)printf("hi\n")
(int) $0 = 3
hi
(lldb)

Il existe une façon intéressante de contourner le problème des arguments à virgule flottante, BTW. Vous créez un fichier "préfixe d'expression" qui est ajouté à chaque expression que vous entrez dans lldb, avec un prototype de vos méthodes de classe. Par exemple, j'ai une classe MyClass qui hérite de NSObject, elle a deux méthodes intéressantes, "setArg:" et "getArg" qui définissent et obtiennent un ivar flottant. C'est un petit exemple idiot, mais il montre comment l'utiliser. Voici un fichier de préfixe que j'ai écrit pour lldb:

@interface NSObject
@end
@interface MyClass : NSObject
- init;
- setArg: (float)arg;
- (float) getArg;
@end

extern "C" {
  int strcmp (const char *, const char *);
  int printf(const char * __restrict, ...);
  void puts (const char *);
}

dans mon ~/.lldbinit fichier que j'ajoute

settings set target.expr-prefix /Users/jason/lldb-prefix.h

et maintenant je peux faire

(lldb)    p [var getArg]
(float) $0 = 0.5
(lldb)    p [var setArg:0.7]
(id) $1 = 0x0000000100104740
(lldb)    p [var getArg]
(float) $2 = 0.7

Vous remarquerez que j'ai inclus quelques fonctions de bibliothèque C standard ici aussi. Après cela, je n'ai plus besoin de lancer les types de retour de ceux-ci, par exemple.

(lldb) p printf("HI\n")
<no result>
HI
(lldb) p strcmp ("HI", "THERE")
(int) $3 = -12

(un correctif pour cette chose "<aucun résultat>" a déjà été validé pour les sources TOT de lldb.)

101
Jason Molenda

Si vous avez besoin de plusieurs lignes, utilisez expression:

expression

do {
  try thing.save()
} catch {
  print(error)
}

// code will execute now

Ligne vide pour terminer et exécuter le code.

4
João Souza