Tests fibonacci - le mystère de la ligne 11

Tests fibonacci - le mystère de la ligne 11

par Nicolas Pierre Raulin,
Number of replies: 7

Bonjour,

Lors des tests de la week 10 – 11 avec "fibonacci.gb", nous tombons sur une "Segmentation fault (core dumped)" qui nous semble inexplicable; je m'explique :


Comme vous pouvez le voir, la ligne 7 est printed, mais la 11 ne l'est pas. Cela nous indique donc que la SegFault intervient dans cpu_cycle(). Lors de l'exécution de cette dernière, la ligne 19 ET la ligne 23 sont printed. La ligne 23 se trouve juste avant le return. Comment donc est-ce possible que la ligne 23 soit printed, mais que la 11 ne le soit pas sachant que cette dernière est l'instruction juste après le return de cpu_cycle() ?

Quelques notes importantes :
  • La Segmentation Fault n'arrive pas tout le temps, mais environ une fois sur deux;
  • Valgrind ne détecte pas de Segmentation Fault;
  • Les tests "unit-test-alu_ext" et "unit-test-cpu-dispatch" passent tous;
  • Les print commençant par un tiret demi cadratin sont des prints internes à cpu_cycles() que j'ai supprimé du screenshot pour ne pas dévoiler le fonctionnement de notre code sur le forum;
  • J'ai essayé de fflush(stderr) (bien que, comme vous l'avez dit, le stderr est printed instantanément) sans succès;
  • Le M_EXIT_IF_ERROR n'influe pas puisque la même erreur apparaît sans (et que puisque la ligne 23 est printed, cpu_cycle() retourne ERR_NONE);
  • La SegFault n'est pas un NullPointerException sur les arguments du fprintf de la ligne 11 puisqu'en rajoutant un fprintf sans argument à la ligne 10, ce dernier n'est pas non plus printed.

Nous n'avons plus d'idée sur la cause de l'erreur... Peut-être pourrez-vous nous envoyer une bouée de sauvetage.

Bonne soirée,
Nicolas Raulin
In reply to Nicolas Pierre Raulin

Re: Tests fibonacci - le mystère de la ligne 11

par Cédric Viaccoz,

Je n'arrive malheureusement pas à voir exactement d'où pourrait venir l'erreur en fonction de ce qui est montré, cependant je peux peut être vous offrir de nouvelles pistes à suivre pour trouver l'erreur:

  • Utiliser un debuggeur. Je comprends la réticence à utiliser un tel programme et s'en référer au printf à la place, mais votre cas me semble être malheureusement un exemple de la limite des printf pour débugger. Commencez par mettre peu de breakpoints (du style un avant et un après l'endroit problématique) puis en ajouter progressivement une fois que vous comprenez un peu mieux l'éxecution du programme dans ce cas problématique. GDB est un débugger accessible par la commande line et qui disponible sur les VM du cours (cf. le tuto du cours). j'ai également eu de très bon échos (et vu l'un d'entre vous l'utiliser avec brio) du débuggeur graphique intégré à VSCode. Plus que des breakpoints, les débuggeurs vous permettent également de voir la stack trace de l'éxecution et d'obtenir plus d'informations contextuelles sur le problème d'un programme.
  • Une "segmentation fault (core dumped) "peut être produite par d'autres problèmes qu'un accès non autorisé de mémoire. Ca peut être églaement un message reçu lorsque la mémoire est corrompu, ce qui arrive notamment lors d'un stack  overflow. Contrôlez que vous n'avez pas une fonction récursive avec une condition d'arrêt incomplète, et contrôlez que vous ne déclarez rien de statique dans vos fonctions qui serait trop lourd (attention notamment à la taille des variable length array).
  • Vous mentionnez que ce problème arrive une fois sur deux, ça peut donc peut être venir d'une présence de valeurs "garbages" à un endroit de votre code. Vérifiez que vous initialisez bien correctement toutes vos variables par défaut. Il est possible que vous lisez une variable non initialisée et selon la chance que vous avez avec le placement peu déterministe de votre RAM, ça fonctionne par moment et à d'autres pas.
In reply to Nicolas Pierre Raulin

Re: Tests fibonacci - le mystère de la ligne 11

par Jonas Blanc,

Salut !

Nous avons le même problème, si ça peut aider, on a une piste:

Lorsque nous branchons le cartridge après le bootrom dans gameboy_create(), (et donc que cartridge override totalement le bootrom) le test tourne à merveille, ce qui voudrait dire que notre potentielle faute vient du côté de bootrom.

Nous sommes avides de toutes avancées sur ce grand mystère. 

Jonas

In reply to Nicolas Pierre Raulin

Re: Tests fibonacci - le mystère de la ligne 11

par Nicolas Pierre Raulin,

Bonjour!

Nous venons de détecter la source du problème (après 47 heures passées sur cette semaine de projet). Je vais répondre aux trois personnes en même temps pour éviter de spammer la boîte mail des gens.


@Cédric Viaccoz

Nous avons utilisé gdb pour détecter l'erreur : juste avant l'entrée dans CHG_U3_HLR, tout va bien. En sortie, la backtrace est corrompue (et prend l'adresse 0xe3f2 qui correspond à 58354 en décimal, cycle exact durant lequel la SegFault apparaissait). Nous n'avions pas accès à l'implémentation de CHG_U3_HLR, mais en rajoutant un breakpoint dans cpu_read_at_idx(), nous avons pu déterminer qu'il s'agissait d'une écriture à un endroit "non autorisé" (cf. réponse à @Jonas Blanc). Merci de nous avoir mis sur la piste!


@Jean-Cédric Chappelier

Tout était ok à ce niveau-là! :)


@Jonas Blanc

Je peux t'expliquer notre erreur pour éviter que ton collègue et toi perdiez trop de temps là-dessus. Dans gameboy_create(), nous créions des component_t (que nous initialisions avec component_create() et pluggions sur le bus). Finalement, nous ajoutions lesdits composants dans l'array de composants de gameboy_t... C'est une mauvaise idée que de passer par des objets temporaires; je te laisse essayer de comprendre pourquoi.


Bonne soirée!
Nicolas Raulin

In reply to Nicolas Pierre Raulin

Re: Tests fibonacci - le mystère de la ligne 11

par Jean-Cédric Chappelier,

> après 47 heures passées sur cette semaine de projet

Non mais il ne FAUT pas faire ça !
Je ne dis pas du tout ça pour critiquer / réprimander ; je suis simplement vraiment et sincèrement navré pour vous.
Qu'aurions nous pu faire pour éviter ça ?

> C'est une mauvaise idée que de passer par des objets temporaires

est-ce que des outils comme valdring et ASAN ne trouvaient pas ça ?

In reply to Jean-Cédric Chappelier

Re: Tests fibonacci - le mystère de la ligne 11

par Mathis Benjamin Manuel Randl,
Je pense que c'est un sentiment général que cette étape a pris bien plus de temps qu'annoncé. Elle n'est pas encore parfaite de notre côté donc je ne donnerai pas de valeurs numériques, mais je n'ai pas l'impression que ce soit un cas isolé
In reply to Jean-Cédric Chappelier

Re: Tests fibonacci - le mystère de la ligne 11

par Joshua Nicholas Pierre Bernimoulin,

est-ce que des outils comme valdring et ASAN ne trouvaient pas ça ?

Malheureusement on pense que c'était un cas de undefined behaviour (en effet ce bug n'était pas systématique). Et on soupçonne  que valgrind et AddressSanitizer change ce comportement car dès qu'on runnait avec valgrind ou compilait avec ASAN le segfault disparaissait et le programme semblait se comporter normalement. 

Aussi, vu que le segfault n'était pas lors de l'écriture, mais bien quand le programme essayait de remonter la backtrace corrompue (et donc segfaultait sur un return 0, ce qui nous a causé beaucoup de confusion), je ne suis pas sur si ces programmes. si ils avait réussi à simuler l'erreur, aurait trouvé sa source.