Quelqu'un peut-il expliquer ce comportement de gdb?
900 memset(&new_ckpt_info,'\0',sizeof(CKPT_INFO));
(gdb)
**903 prev_offset = cp_node->offset;**
(gdb)
**905 m_CPND_CKPTINFO_READ(ckpt_info,(char *)cb->shm_addr.ckpt_addr+sizeof(CKPT_** HDR),i_offset);
(gdb)
**903 prev_offset = cp_node->offset;**
(gdb)
**905 m_CPND_CKPTINFO_READ(ckpt_info,(char *)cb->shm_addr.ckpt_addr+sizeof(CKPT_ HDR),i_offset);**
(gdb)
**908 bitmap_offset = client_hdl/32;**
(gdb)
**910 bitmap_value = cpnd_client_bitmap_set(client_hdl%32);**
(gdb)
**908 bitmap_offset = client_hdl/32;**
(gdb)
**910 bitmap_value = cpnd_client_bitmap_set(client_hdl%32);**
(gdb)
**908 bitmap_offset = client_hdl/32;**
(gdb)
**910 bitmap_value = cpnd_client_bitmap_set(client_hdl%32);**
(gdb)
913 found = cpnd_find_exact_ckptinfo(cb , &ckpt_info , bitmap_offset , &offset , &prev_offset);
(gdb)
916 if(!found)
(gdb) p found
$1 = <value optimized out>
(gdb) set found=0
Left operand of assignment is not an lvalue.
Pourquoi après avoir exécuté la ligne 903, il exécute à nouveau la même chose pour 905 908 910?
Une autre chose est found
une bool
variable de type -type, alors pourquoi est-elle affichée value optimized out
? Je ne suis pas en mesure de définir la valeur de found
.
Cela semble être une optimisation du compilateur (dans ce cas, son -O2
); comment puis-je encore définir la valeur de found
?
Réponses:
Pour déboguer du code optimisé, apprenez le langage assembleur / machine.
Utilisez le mode GDB TUI. Ma copie de GDB l'active lorsque je tape le moins et Entrée. Tapez ensuite Cx 2 (c'est-à-dire maintenez la touche Control enfoncée et appuyez sur X, relâchez les deux puis appuyez sur 2). Cela le mettra dans l'affichage de la source partagée et du démontage. Utilisez ensuite
stepi
etnexti
pour déplacer une instruction machine à la fois. Utilisez Cx o pour basculer entre les fenêtres TUI.Téléchargez un PDF sur le langage machine de votre CPU et les conventions d'appel de fonction. Vous apprendrez rapidement à reconnaître ce qui est fait avec les arguments de fonction et les valeurs de retour.
Vous pouvez afficher la valeur d'un registre en utilisant une commande GDB comme
p $eax
la source
Recompiler sans optimisations (-O0 sur gcc).
la source
Déclarer trouvé comme "volatile". Cela devrait dire au compilateur de NE PAS l'optimiser.
volatile int found = 0;
la source
Le compilateur commencera à faire des choses très intelligentes avec les optimisations activées. Le débogueur montrera le code sautant en avant et en arrière beaucoup en raison de la manière optimisée de stocker les variables dans les registres. C'est probablement la raison pour laquelle vous ne pouvez pas définir votre variable (ou dans certains cas voir sa valeur) car elle a été intelligemment répartie entre les registres pour la vitesse, plutôt que d'avoir un emplacement mémoire direct auquel le débogueur peut accéder.
Compiler sans optimisations?
la source
En règle générale, les valeurs booléennes utilisées dans les branches immédiatement après avoir été calculées de cette manière ne sont jamais réellement stockées dans des variables. Au lieu de cela, le compilateur dérive simplement directement les codes de condition définis à partir de la comparaison précédente. Par exemple,
int a = SomeFunction(); bool result = --a >= 0; // use subtraction as example computation if ( result ) { foo(); } else { bar(); } return;
Compile généralement en quelque chose comme:
call .SomeFunction ; calls to SomeFunction(), which stores its return value in eax sub eax, 1 ; subtract 1 from eax and store in eax, set S (sign) flag if result is negative jl ELSEBLOCK ; GOTO label "ELSEBLOCK" if S flag is set call .foo ; this is the "if" black, call foo() j FINISH ; GOTO FINISH; skip over the "else" block ELSEBLOCK: ; label this location to the assembler call .bar FINISH: ; both paths end up here ret ; return
Remarquez que le "booléen" n'est jamais stocké nulle part.
la source
Vous ne pouvez pratiquement pas définir la valeur de found. Déboguer des programmes optimisés en vaut rarement la peine, le compilateur peut réorganiser le code de manière à ce qu'il ne corresponde en aucun cas au code source (autre que de produire le même résultat), déroutant ainsi les débogueurs sans fin.
la source
Lors du débogage de programmes optimisés (ce qui peut être nécessaire si le bogue n'apparaît pas dans les versions de débogage), vous devez souvent comprendre le compilateur d'assembly généré.
Dans votre cas particulier, la valeur de retour de
cpnd_find_exact_ckptinfo
sera stockée dans le registre qui est utilisé sur votre plateforme pour les valeurs de retour. Surix86
, ce serait%eax
. Surx86_64
:%rax
etc.Vous pouvez examiner ce registre dans
GDB
et vous pouvez le définir. Par exemple surix86
:(gdb) p $eax (gdb) set $eax = 0
la source
J'utilise QtCreator avec gdb.
Ajouter
Fonctionne bien pour moi
la source