J'ai une fonction C à un seul trait qui est juste return value * pow(1.+rate, -delay);
- elle actualise une future valeur à une valeur actuelle. La partie intéressante du démontage estPourquoi FLD1 charge-t-il NaN à la place?
0x080555b9 : neg %eax 0x080555bb : push %eax 0x080555bc : fildl (%esp) 0x080555bf : lea 0x4(%esp),%esp 0x080555c3 : fldl 0xfffffff0(%ebp) 0x080555c6 : fld1 0x080555c8 : faddp %st,%st(1) 0x080555ca : fxch %st(1) 0x080555cc : fstpl 0x8(%esp) 0x080555d0 : fstpl (%esp) 0x080555d3 : call 0x8051ce0 0x080555d8 : fmull 0xfffffff8(%ebp)
Bien que simple pas à pas dans cette fonction, gdb dit (taux est de 0,02, le retard est 2, vous pouvez les voir sur la pile):
(gdb) si 0x080555c6 30 return value * pow(1.+rate, -delay); (gdb) info float R7: Valid 0x4004a6c28f5c28f5c000 +41.68999999999999773 R6: Valid 0x4004e15c28f5c28f6000 +56.34000000000000341 R5: Valid 0x4004dceb851eb851e800 +55.22999999999999687 R4: Valid 0xc0008000000000000000 -2 =>R3: Valid 0x3ff9a3d70a3d70a3d800 +0.02000000000000000042 R2: Valid 0x4004ff147ae147ae1800 +63.77000000000000313 R1: Valid 0x4004e17ae147ae147800 +56.36999999999999744 R0: Valid 0x4004efb851eb851eb800 +59.92999999999999972 Status Word: 0x1861 IE PE SF TOP: 3 Control Word: 0x037f IM DM ZM OM UM PM PC: Extended Precision (64-bits) RC: Round to nearest Tag Word: 0x0000 Instruction Pointer: 0x73:0x080555c3 Operand Pointer: 0x7b:0xbff41d78 Opcode: 0xdd45
Et après la fld1
:
(gdb) si 0x080555c8 30 return value * pow(1.+rate, -delay); (gdb) info float R7: Valid 0x4004a6c28f5c28f5c000 +41.68999999999999773 R6: Valid 0x4004e15c28f5c28f6000 +56.34000000000000341 R5: Valid 0x4004dceb851eb851e800 +55.22999999999999687 R4: Valid 0xc0008000000000000000 -2 R3: Valid 0x3ff9a3d70a3d70a3d800 +0.02000000000000000042 =>R2: Special 0xffffc000000000000000 Real Indefinite (QNaN) R1: Valid 0x4004e17ae147ae147800 +56.36999999999999744 R0: Valid 0x4004efb851eb851eb800 +59.92999999999999972 Status Word: 0x1261 IE PE SF C1 TOP: 2 Control Word: 0x037f IM DM ZM OM UM PM PC: Extended Precision (64-bits) RC: Round to nearest Tag Word: 0x0020 Instruction Pointer: 0x73:0x080555c6 Operand Pointer: 0x7b:0xbff41d78 Opcode: 0xd9e8
après cela, tout va en enfer. Les choses deviennent grossièrement ou sous-évaluées, donc même s'il n'y avait pas d'autres bugs dans ma tentative d'IA freeciv, il choisirait toutes les mauvaises stratégies. Comme envoyer toute l'armée dans l'Arctique. (Soupir, si seulement je devais aller aussi loin.)
Je dois manquer quelque chose d'évident, ou être aveuglé par quelque chose, parce que je ne peux pas croire que fld1
devrait jamais échouer. Encore moins qu'il ne devrait échouer qu'après une poignée de passes à travers cette fonction. Lors des passes précédentes, la FPU charge correctement 1 dans ST (0). Les octets à 0x080555c6 codent définitivement fld1
- vérifié avec x/... sur le processus en cours d'exécution.
Ce qui donne?
Ah, vous les gars rock! Merci! Cela me conduisait au mur. Quant à savoir pourquoi cela se produit: probablement parce que j'avais déplacé une fonction en appelant une autre qui renvoie 'double' d'un fichier à l'autre, et dans le nouveau fichier, il n'y avait pas de prototype pour la fonction à virgule flottante. la valeur de retour de la pile. Je m'attendais à être à court de pile FP beaucoup plus tôt cependant, mais maintenant il semble fonctionner beaucoup mieux maintenant que j'ai fourni un prototype. Maintenant, je peux passer à la prochaine erreur de segmentation! –
@Bernd: Oui, cela peut certainement causer ce genre de problème. –