mercredi 27 juillet 2011

Read

"Mais pourquoi", me demande mon collègue, "est-ce que mon programme fonctionne quand je le débugge, mais pas lorsque je l'exécute? On dirait qu'il attrape de mauvais paquets du réseau, et il se retrouve à lire n'importe quoi."

Arf, du C#. Tentons d'y voir clair.

D'habitude, j'ai absolument horreur de débugger un programme qui ne donne pas les mêmes résultats lorsqu'il tourne dans un débuggeur. Mais là, il m'a semblé que ça ne devait pas être trop difficile. Déjà, il fut facile de s'en assurer, ce n'était pas le débuggeur, mais les breakpoints. Sans breakpoints, le programme foirait, semblant effectivement lire des données pourries sur le réseau. Avec breakpoints, ça passait.

Je tentais de voir quels étaient les breakpoints "magiques", en les ajoutant et les retirant suivant la rigoureuse méthode de Monte Carlo (c'est à dire au pif). Finalement, une ligne attira mon attention. Quelque chose comme:


networkStream.Read(data, length);

Je changeais prestement la ligne pour afficher côte à côte "length" et la valeur de retour de la méthode. S'affiche:

67889 - 1280

Tête du collègue médusé. Eh oui. Même en C#, et comme en C, "Read" va lire et retourner ce qu'il trouve dans le tampon, et peut donc renvoyer moins que la taille demandée. Le breakpoint permettait simplement à l'ensemble du paquet d'arriver dans le tampon, et donc de faire fonctionner le programme (le contenu des données était ignoré). Mais lors d'une exécution normale, Read était appelé avant que tout le paquet ne soit arrivé. Lors de la deuxième lecture, c'était la fin du premier paquet qui passait, et qui était donc interprété en dépit du bon sens.

Je dirigeais mon coreligionnaire vers une méthode à nous, répondant au doux nom de ReadExactly, et implémentée avec une belle boucle qui accumulait les Read jusqu'à la taille désirée.

Aucun commentaire: