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 que found
est une variable de type bool
-, alors pourquoi affiche-t-il value optimized out
? Je ne peux pas non plus définir la valeur de found
.
Cela semble être une optimisation du compilateur (dans ce cas sa -O2
); comment puis-je toujours définir la valeur de found
?
Pour déboguer un 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. Ensuite, tapez C-x 2 (maintenez enfoncée la touche Ctrl et appuyez sur X, relâchez les deux puis appuyez sur 2). Cela le mettra en source scindée et en affichage de désassemblage. Ensuite, utilisez stepi
et nexti
pour déplacer une instruction machine à la fois. Utilisez C-x o pour basculer entre les fenêtres TUI.
Téléchargez un PDF) sur le langage machine de votre CPU et sur les conventions d’appel des fonctions. Vous apprendrez rapidement à reconnaître ce que vous faites avec les arguments et les valeurs de fonction.
Vous pouvez afficher la valeur d’un registre à l’aide d’une commande GDB telle que p $eax
Recompiler sans optimisations (-O0 sur gcc).
Déclarez trouvé comme "volatil". Cela devrait indiquer au compilateur de ne PAS l'optimiser.
volatile int found = 0;
Le compilateur commencera à faire des choses très intelligentes avec des optimisations activées. Le débogueur montrera le code sautant en avant et en arrière beaucoup en raison de la façon optimisée la façon dont les variables sont stockées 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 de disposer d'un emplacement de mémoire direct auquel le débogueur peut accéder.
Compiler sans optimisations?
En règle générale, les valeurs booléennes utilisées dans les branches immédiatement après leur calcul ne sont jamais stockées dans des variables. Au lieu de cela, le compilateur se branche directement sur les codes de condition qui ont été 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 habituellement à 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 comment le "bool" n'est jamais stocké nulle part.
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 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 plate-forme pour les valeurs de retour. Sur ix86
, Ce serait %eax
. Sur x86_64
: %rax
, Etc. Vous aurez peut-être besoin de google pour la 'convention d'appel de la procédure [de votre processeur]' si ce n'est pas le cas.
Vous pouvez examiner ce registre dans GDB
et vous pouvez le définir. Par exemple. sur ix86
:
(gdb) p $eax
(gdb) set $eax = 0
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 aucune manière au code source (autre que produire le même résultat), ce qui confond indéfiniment les débogueurs.
J'utilise QtCreator avec gdb.
Ajouter
QMAKE_CXXFLAGS += -O0
QMAKE_CXXFLAGS -= -O1
QMAKE_CXXFLAGS -= -O2
QMAKE_CXXFLAGS -= -O3
Fonctionne bien pour moi