Tuto pour utiliser le Debugger ?

AliGatorAliGator Membre, Modérateur
Bonjour à  tous,

J'ai eu à  l'instant à  traiter avec un bug dans mon appli que j'ai mis du temps à  trouver*... et du coup lors de mes recherches pour tracker ce bug (plantage de l'appli de temps en temps quand je passais trop souvent d'une vue à  l'autre dans mon appli iPhone NavigationBased), j'ai voulu essayer d'utiliser le debugger... ::)

Bon j'ai rarement eu l'occasion de l'utiliser, en général je met des NSLogs partout comme beaucoup (mais là  il ne m'indiquait aucun message lorsqu'il plantait, alors ça n'aidait pas...) du coup je l'ai jamais vraiment maà®trisé et m'y suis souvent perdu... Et je réalise qu'apparemment je ne suis pas le seul dans ce cas ! ;)

Un bon petit tuto serait peut-être le bienvenu si une bonne âme se sentait d'attaque  :o

En fait y'a plein de trucs qui me posent un peu problème :
  • J'ai beau compiler en mode "Debug" et avoir placé des breakpoints en cliquant dans la gouttière à  gauche dans l'éditeur de code, les Breakpoints n'ont pas l'air d'être activés. Si je vais dans la fenêtre Breakpoints, ils apparaissent ni cochés ni décochés mais avec un tiret (la checkbox en "mixed state"). Dans la doc Apple que j'ai un peu fouillé à  ce sujet, ils disent que c'est parce que le symbole n'a pas été encore chargé... mais je peux attendre (et faire en sorte qu'on passe dans mon code où y'a le BP) il passe jamais en coché. Il faut que je le coche moi-même pour qu'enfin il s'active... et ce à  chaque session d'exécution !! Ca me parait bien bizarre...
  • Si je crée un nouveau "Symbolic Breakpoint" dans la fenêtre Breakpoints et que comme nom je met le nom d'un sélecteur quelconque genre "viewDidLoad" (je teste sous iPhone), le breakpoint n'est jamais appelé pour autant (en action associé j'ai demandé un log d'un texte, je le vois jamais dans la console)
  • Du coup avec tout ça moi qui m'attendais à  juste avoir à  cliquer dans la gouttière pour placer des breakpoints, lancer mon appli, et qu'il s'arrête à  mes BP que je puisse regarder un peu le contenu de mes variables... c'est pas gagné
  • En plus quand je regarde la CallStack, tout le code associé aux entrées de la CallStack est en assembleur, à  part le code que j'ai écrit moi-même... En même temps ça c'est sans doute lié au fait que je développe sur l'iPhone Simulator et qu'il a l'air de vouloir charger les debug symbol des frameworks OSX et non iPhone SDK. Car à  chaque fois au début de la session gdb il m'affiche :

    This GDB was configured as "i386-apple-darwin".warning: Unable to read symbols for "/System/Library/Frameworks/UIKit.framework/UIKit" (file not found).
    warning: Unable to read symbols from "UIKit" (not yet mapped into memory).
    warning: Unable to read symbols for "/System/Library/Frameworks/CoreGraphics.framework/CoreGraphics" (file not found).
    warning: Unable to read symbols from "CoreGraphics" (not yet mapped into memory).
    Donc j'ai l'impression qu'il ne va pas chercher les debugsymbols au bon endroit, mais je ne sais pas comment lui indiquer les bons emplacements...


Bref pas très motivant pour utiliser le debugger tout ça, quand pas grand chose ne marche pour pas dire rien quand on veut l'utiliser, ça donne l'impression qu'il est bien compliqué alors que j'imagine que c'est 3x rien... Donc un petit topo pas-à -pas de comment placer un breakpoint et simplement voir les valeurs ensuite (penser à  faire Run->Debug j'imagine et non Run->Run dans Xcode ? quoique j'ai l'impression que ça marche aussi ?!) et tout... Merci d'avance



___
*bon à  savoir : lorsqu'on affecte le delegate d'une UIWebView, par exemple qu'on relie l'IBOutlet delegate d'une UIWebView à  un objet dans IB, il faut absolument faire [tt]webView.delegate = nil;[/tt], typiquement dans le dealloc du delegate lui-même, c'est indiqué dans la doc de UIWebViewDelegate mais faut le savoir, c'est pas habituel et ça m'a pris du temps !

Réponses

  • schlumschlum Membre
    05:54 modifié #2
    Leur interface sur gdb est pourrite... Vive l'utilisation en ligne de commande  ;)
  • AliGatorAliGator Membre, Modérateur
    05:54 modifié #3
    Oulà , c'est pas encourageant ce genre de réponse lol :)
  • schlumschlum Membre
    05:54 modifié #4
    dans 1228007767:

    Si je crée un nouveau "Symbolic Breakpoint" dans la fenêtre Breakpoints et que comme nom je met le nom d'un sélecteur quelconque genre "viewDidLoad" (je teste sous iPhone), le breakpoint n'est jamais appelé pour autant (en action associé j'ai demandé un log d'un texte, je le vois jamais dans la console)


    En fait, il faut mettre "- [NomObjet viewDidLoad]"  ;)
    (remplacer '-' par '+' en cas de méthode de Classe !)
  • schlumschlum Membre
    05:54 modifié #5
    dans 1228007767:

    Car à  chaque fois au début de la session gdb il m'affiche :

    This GDB was configured as "i386-apple-darwin".warning: Unable to read symbols for "/System/Library/Frameworks/UIKit.framework/UIKit" (file not found).
    warning: Unable to read symbols from "UIKit" (not yet mapped into memory).
    warning: Unable to read symbols for "/System/Library/Frameworks/CoreGraphics.framework/CoreGraphics" (file not found).
    warning: Unable to read symbols from "CoreGraphics" (not yet mapped into memory).

    Donc j'ai l'impression qu'il ne va pas chercher les debugsymbols au bon endroit, mais je ne sais pas comment lui indiquer les bons emplacements...


    Un problème de SDK ?
    http://discussions.apple.com/thread.jspa?messageID=7727997

    Est-ce qu'en mode Debug, ton SDK est bien le SDK de l'iPhone avec le bon chemin ?
  • AliGatorAliGator Membre, Modérateur
    05:54 modifié #6
    dans 1228018113:

    dans 1228007767:

    Si je crée un nouveau "Symbolic Breakpoint" dans la fenêtre Breakpoints et que comme nom je met le nom d'un sélecteur quelconque genre "viewDidLoad" (je teste sous iPhone), le breakpoint n'est jamais appelé pour autant (en action associé j'ai demandé un log d'un texte, je le vois jamais dans la console)


    En fait, il faut mettre "- [NomObjet viewDidLoad]"  ;)
    (remplacer '-' par '+' en cas de méthode de Classe !)
    Et si je veux qu'il break sur la méthode quel que soit l'objet ? :P
    Par "NomObjet" tu entends quoi ? Je veux dire, c'est pas un nom de variable (genre ici une variable de type UIViewController) j'imagine, puisque les variables ne sont que des noms symboliques pouvant stocker un objet à  un moment de l'exécution et un autre à  un autre moment, et en plus dépendent du contexte (on peut très bien avoir 2 variables de même nom dans deux méthodes différentes)...

    Donc ici ce serait du genre "-[UIViewController viewDidLoad]" qu'il faut mettre, viewDidLoad étant une méthode d'instance de la classe UIViewController, pour qu'il break à  chaque fois que cette méthode est appellée quel que soit l'objet sur lequel elle est appelée ?

  • AliGatorAliGator Membre, Modérateur
    05:54 modifié #7
    dans 1228018651:

    Un problème de SDK ?
    http://discussions.apple.com/thread.jspa?messageID=7727997

    Est-ce qu'en mode Debug, ton SDK est bien le SDK de l'iPhone avec le bon chemin ?
    Ben justement c'est ça qui m'étonne et que je capte pas...
    En Debug, j'ai :
    - Menu Project > Set Active SDK = "Simulator - iPhone OS 2.1"
    - Pomme-I sur mon Projet --> Base SDK for all configurations = "Simulator - iPhone OS 2.1" (que je retrouve dans l'onglet "build", ligne "Base SDK")
    - Pomme-I sur mon Target > onglet Build -> Base SDK = "Simulator - iPhone OS 2.1" aussi
    Donc tout est cohérent de ce côté.

    Dans mon projet j'ai 3 frameworks : UIKit, Foundation, et CoreGraphics. Les 3 ont comme "Path Type" la mention "Relative to SDK", ce qui fait que leur "Full Path" est bien dans "/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator2.1.sdk/..."

    Avant pour le projet j'avais en effet "Device - iPhone OS 2.1" et non Simulator (pour info je n'ai ni iPhone ni iPod Touch j'ai toujours testé qu'avec le simulateur) mais bon mm en mettant tout sur "Simulator", lorsque je lance en mode Debug (Pomme-Alt-Y) gdb s'attache au programme et... me met donc toujours ces mêmes lignes :(
  • Philippe49Philippe49 Membre
    05:54 modifié #8
    dans 1228007767:

    Un bon petit tuto serait peut-être le bienvenu si une bonne âme se sentait d'attaque 

    C'est vrai que cela serait bien utile, surtout que maintenant dès qu'un bug apparaà®t, l'appli se met en mode debug.



    dans 1228007767:

    ___
    *bon à  savoir : lorsqu'on affecte le delegate d'une UIWebView, par exemple qu'on relie l'IBOutlet delegate d'une UIWebView à  un objet dans IB, il faut absolument faire [tt]webView.delegate = nil;[/tt], typiquement dans le dealloc du delegate lui-même, c'est indiqué dans la doc de UIWebViewDelegate mais faut le savoir, c'est pas habituel et ça m'a pris du temps !


    Tu as rencontré ce phénomène sur d'autre delegate ?
    Cela fait un release sur le delegate lui-même ... mais normalement une property(retain) subit un release dans le dealloc d'une classe correctement faite. Alors ce webView.delegate = nil; ferait-il autre chose ?
  • AliGatorAliGator Membre, Modérateur
    05:54 modifié #9
    dans 1228030892:

    Tu as rencontré ce phénomène sur d'autre delegate ?
    Cela fait un release sur le delegate lui-même ... mais normalement une property(retain) subit un release dans le dealloc d'une classe correctement faite. Alors ce webView.delegate = nil; ferait-il autre chose ?
    Ben justement non pas que je sache, c'est le seul delegate qui m'a posé problème.
    Quand il plantait (je stressait un peu mon navigationController en changeant de ViewController bien vite exprès) le debugguer s'arrêtait sur le Thread-1 sur je sais plus quoi au juste, mais genre couches basses qui me disaient rien... Mais en regardant dans le Thread-2, je me suis apperçu qu'il essayait d'envoyer un message au delegate de ma WebView (pour m'informer que la requête était arrivée) alors que mon delegate n'existait plus justement. C'est ce qui a fini par me mettre la puce à  l'oreille.

    Et là  dans la doc de UIWebViewDelegate je lis du coup :
    Important: Before releasing an instance of UIWebView for which you have set a delegate, you must first set the UIWebView delegate property to nil before disposing of the UIWebView instance. This can be done, for example, in the dealloc method where you dispose of the UIWebView.
    Donc c'est écrit dans la doc y'a pas à  gueuler là -dessus, mais c'est pas usuel quand même, ça m'a l'air spécifique au delegate de UIWebView... donc faut le savoir !
  • schlumschlum Membre
    novembre 2008 modifié #10
    dans 1228024669:

    Et si je veux qu'il break sur la méthode quel que soit l'objet ? :P


    Je ne crois pas que ça soit possible  :( Il faut peut-être dans ce cas plutôt mettre un breakpoint sur "objc_msgSend" avec une conditionnelle sur le selecteur, mais je ne sais pas si ça fonctionne bien la comparaison de sélecteurs dans gdb  B)

    Par "NomObjet" tu entends quoi ? Je veux dire, c'est pas un nom de variable (genre ici une variable de type UIViewController) j'imagine, puisque les variables ne sont que des noms symboliques pouvant stocker un objet à  un moment de l'exécution et un autre à  un autre moment, et en plus dépendent du contexte (on peut très bien avoir 2 variables de même nom dans deux méthodes différentes)...

    Donc ici ce serait du genre "-[UIViewController viewDidLoad]" qu'il faut mettre, viewDidLoad étant une méthode d'instance de la classe UIViewController, pour qu'il break à  chaque fois que cette méthode est appellée quel que soit l'objet sur lequel elle est appelée ?


    Oui da, le nom de la classe...
  • KiwixKiwix Membre
    octobre 2009 modifié #11
    De façon générale, pour débuter avec le Débugeur le plus sûr est de passer par les menus :
    Run --> Manage Breakpoints --> Add Breakpoint at Current Line
    ensuite pour entrer en mode debug (et donc s'arrêter aux breakpoints placés ou faire du pas-à -pas) il faut passer par :
    Run --> Debug

    Par contre si quelqu'un sait comment placer des breakpoints dans un projet inclus sous forme de librairie statique dans un autre projet (celui que l'on veut exécuter) je suis preneur!  :why?:
  • schlumschlum Membre
    05:54 modifié #12
    Il faut ajouter les bp à  la main... C'est gdb qui est derrière, et la configuration manuelle permet bien plus de choses que les " menus ".
    Dans la console, taper "help break"
  • AliGatorAliGator Membre, Modérateur
    05:54 modifié #13
    Heu pourtant je le fait actuellement avec un de mes projets :
    Un projet "Lib" qui build une librairie statique, et un projet "App" qui inclus cette lib statique.
    J'ai ajouté le projet "Lib" dans le projet "App" (ce qui fait que dans "Groups & Files", sous l'icône de mon projet "App", le premier élément que je trouve dedans avant mon groupe "Classes" c'est le projet "Lib", et quand j'ouvre son petit triangle je vois les targets de ma lib, donc le fichier .a, qui est listé). Ceci me permet d'ajouter mon Lib.a en tant que "Direct Dependancy" de mon target "App", m'assurant que ma librairie est recompilée si elle n'est pas à  jour avant de compiler l'application.

    Eh bien avec tout ça, j'ai mis un breakpoint dans mon projet Lib (que j'ai ouvert en parallèle de mon projet App) et quand je lance mon appli App en mode debug, les breakpoints tant de App que ceux de Lib sont pris en compte.
  • 05:54 modifié #14
    Il y a un bouquin qui à  l'air pas mal pour apprendre à  "dompter" le debugger c'est XCode 3 unreashed, quelqu'un la déjà  lu ?

    http://www.amazon.fr/Xcode-3-Unleashed-Fritz-Anderson/dp/0321552636

    (en anglais bien sûr... >:D)
  • schlumschlum Membre
    05:54 modifié #15
    Y a "man gdb" aussi  :P
  • octobre 2009 modifié #16
    C'est sur  ;D , ou aussi
    file:///Developer/Documentation/DocSets/com.apple.ADC_Reference_Library.DeveloperTools.docset/Contents/Resources/Documents/documentation/DeveloperTools/gdb
Connectez-vous ou Inscrivez-vous pour répondre.