Dans le domaine du débogage, rencontrer des entrées énigmatiques dans les traces de pile de panique peut être déroutant. Un tel cas se présente lors de l'analyse de la sortie d'un simple programme Go :
<code class="go">package main func F(a int) { panic(nil) } func main() { F(1) }</code>
Lors de son exécution, le programme produit une trace de pile imprévue :
panic: nil goroutine 1 [running]: main.F(0x1, 0x10436000) /tmp/sandbox090887108/main.go:4 +0x20 main.main() /tmp/sandbox090887108/main.go:8 +0x20
Le deuxième nombre dans le cadre de pile , 0x10436000, reste insaisissable dans son objectif. Pour déchiffrer cette énigme, nous devons nous plonger dans les subtilités de la représentation de la mémoire de Go et de la génération de traces de pile. les données affichées dans la trace de la pile proviennent des arguments de la fonction, mais leurs valeurs diffèrent de celles explicitement transmises. La raison réside dans la façon dont les arguments sont stockés et imprimés dans certaines architectures de mémoire.
Plus précisément, dans le cas de la environnement de jeu utilisé, une architecture de mots de 64 bits avec des pointeurs de 32 bits (GOARCH=amd64p32) entre en jeu. Cette combinaison particulière entraîne l'impression des arguments sous forme de valeurs de la taille d'un pointeur, ce qui coïncide généralement avec la taille du mot natif. Cependant, dans ce cas, la taille du mot est deux fois supérieure à la taille du pointeur.Par conséquent, chaque mot de 64 bits peut contenir deux arguments, ce qui conduit à l'impression d'un nombre pair de valeurs dans les arguments du cadre. Les données présentées sont essentiellement les valeurs d'arguments brutes stockées dans des morceaux de la taille d'un pointeur.
Autres exemples : Explorer la variabilité de la représentation des donnéesPour illustrer ce phénomène, considérons le fonction suivante :
Lorsqu'elle est appelée avec l'argument 1, la trace de pile révèle :
Ici, seuls les 8 premiers bits du mot de 64 bits sont utilisés, représentant la valeur 1. Les bits restants sont simplement des parties inutilisées du mot de 64 bits.
<code class="go">func F(a uint8) { panic(nil) }</code>
main.F(0x97301, 0x10436000)
indiquant deux mots alloués aux arguments.
<code class="go">func F(a, b, c uint32)</code>
Valeurs de retour : dévoiler la présence cachée dans les traces de pile
main.F(0x100000001, 0xc400000001)
Les cadres de pile intègrent également des valeurs de retour, qui sont allouées sur la pile. Par exemple :
Sur amd64, les arguments du cadre de pile apparaîtront comme :
Le premier mot représente l'argument d'entrée, tandis que les deux mots restants contiennent les valeurs de retour.
<code class="go">func F(a int64) (int, int)</code>
Conclusion
main.F(0xa, 0x1054d60, 0xc420078058)
Comprendre les subtilités de la représentation de la mémoire et de la génération de traces de pile dans Go permet aux développeurs de déchiffrer même les entrées les plus énigmatiques dans les traces de pile de panique. En résolvant l'énigme du « champ inconnu », les programmeurs peuvent déboguer et résoudre efficacement les problèmes, obtenant ainsi des informations inestimables sur le fonctionnement interne de leur code.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!