Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Bug indétectable via printf() / cout

148 réponses
Avatar
AG
Bonjour =E0 tous,

Je travaille dans une =E9quipe de personnes pour lesquels le d=E9bugger
n'est pas l'outil qui tombe sous le sens lorsqu'il s'agit de trouver
les bugs des outils qu'ils ont d=E9velopp=E9.

Afin de les sensibiliser, je recherche un exemple de bug difficile
(voir impossible) a d=E9tecter via des printf()/cout qui n'afficheraient
que les contenus des variables. (Je me rends bien compte qu'on doit
pouvoir tout d=E9bugger avec printf()/cout, mais il faut parfois
afficher les adresses des variable (en plus de leur valeur), voir
parfois la m=E9moire =E0 certains endroits.)

Je voudrais construire un exemple simple (notions de C++ pas trop
compliqu=E9es) et court (un seul fichier, 100 lignes max) pour qu'on
puisse l'=E9tudier en un quart d'heure, mais le d=E9bugger en un temps
presque infini sans d=E9bugger.

Il est possible que l'exemple, puisqu'il y a un bug, d=E9pende de la
plateforme mais c'est un peu in=E9vitable.

L'id=E9al serait que le plantage ait lieu bien apr=E8s le bug...=E7a rajout=
e
du piment. Bref, vous voyez l'id=E9e quoi...

J'avais plusieurs pistes d'exploitation de bug:

Piste 1:
Boucle for d=E9croissante sur un entier non sign=E9 : for(size_t i =3D N;
0<=3D i; i--)

Piste 2:
comparaison de double : double x; ... ; x =3D=3D 0.0

Piste 3:
retour de malloc() non test=E9

Piste 4:
caract=E8re de fin de ligne non test=E9 (\0)

Mais jusque l=E0, je crains qu'il ne soit trop facile de d=E9tecter le
bug

J'ai donc ensuite pens=E9 aux r=E9f=E9rences. Mais ce code est encore un pe=
u
trop voyant. Dans le main(), on peut facilement se demander pourquoi
f1 et f2 sont des r=E9f=E9rences, ce qui met directement la puce =E0
l'oreille. Peut =EAtre trouvez vous ce code bien trop compliqu=E9, ou
auriez vous en t=EAte un mani=E8re de "l'am=E9liorer" :-)

A bon entendeur salut.

AG.




#include <iostream>

using namespace std;

#define BUFFER_LENGTH 10

template<int N, class T>
class fifo_circular
{
private:
T * position;
size_t pos_offset;
T buffer[N];

public:
fifo_circular() { pos_offset =3D N-1; position =3D buffer + pos_offset;
for(int i=3D0;i<N;i++) buffer[i]=3DT(0);};

T step(T &input)
{
*position =3D input;

if(pos_offset>0) // ici il y aurait peut =EAtre moyen de glisser le
bug de la piste 1
pos_offset--;
else
pos_offset =3D N-1;

position =3D buffer + pos_offset;
return *position;
};

template<int M, class U> friend ostream & operator<<(ostream & o,
const fifo_circular<M,U> &f);
};

template<int N, class T>
fifo_circular<N,T> & Init(T & value)
{
fifo_circular<N,T> & f =3D fifo_circular<N,T>(); // h=E9 h=E9 h=E9

for(size_t i =3D 0; i < N; i++)
f.step(value);
return f;
}

template<int M, class U>
ostream & operator<<(ostream & o, const fifo_circular<M,U> &f)
{
for(size_t i =3D 0; i < M; i++)
o << f.buffer[i] << " ";
return o;
}

int main(int argc, char * argv[])
{
int a =3D 1;
fifo_circular<5,int> & f1 =3D Init<5,int>(a); // ici, c'est un peu trop
voyant. On se demande pourquoi f1 est d=E9clar=E9 en tant que
r=E9f=E9rence...
a =3D 2;
fifo_circular<5,int> & f2 =3D Init<5,int>(a);

cout << "fifo f1: " << f1 << "\n";
cout << "fifo f2: " << f2 << "\n";

return 0;
}

10 réponses

1 2 3 4 5
Avatar
James Kanze
On Nov 30, 1:43 pm, AG wrote:
On Nov 30, 2:27 pm, Marc Boyer
wrote:



> Mais est-ce grave ? J'avoue ne quasiment jamais me servir de
> débugger. Je travaille surtout en précondition/invariant
> (assert) + tests unitaires, et éventuellement valgrind quand
> je soupsonne une corruption mémoire.



> Et une fois le bug identifié, à grand coups de cerr
> + assert.



> D'autant que souvent, le bug n'apparait pas en mode débug ;-)



Je pense que c'est grave effectivement. Tout ce que tu écris
pour débugger est inutile avec un débugger. C'est donc un gain
de temps immédiat.



Tu vas prétendre que la spécification des préconditions et des
invariants n'est pas nécessaire ? Qu'on peut se passer des tests
unitaires ?

Je n'aimerais pas à avoir à maintenir du code que tu as écrit.
Ni de m'en servir.

Ensuite d'aucun diront que leur debugger (type gdb) est mal
pratique...peut être. Mais avec un débugger pratique, c'est un
gain de temps certain.



Dans certains cas où le code a été mal écrit, sans
spécifications des interfaces et sans documentation, c'est une
aide à la compréhense. Mais la nécessité d'utiliser un
déboggueur est toujours une reconnaissance que le code a été
écrit sans respecter les règles les plus simple de qualité. Et
que le code coûte beaucoup plus cher que s'il avait été écrit
correctement au départ.

Cela dit, qu'on me le dise si les debugger ne sont pas
intensivement utilisés dans l'industrie, je serais content de
me tromper. Dans mon entourage, tout ceux à qui j'ai montré un
debugger pratique l'ont adopté.



PS: tes élèves, tu ne leur apprends pas le débugger ?



Aux élèves, il faudrait plutôt l'interdire. Il vaut mieux leur
apprendre d'écrire du code correctement, pourqu'ils n'en ont pas
besoin d'un déboggueur.

--
James Kanze
Avatar
AG
On Nov 30, 5:10 pm, Fabien LE LEZ wrote:

Ces deux-là sont extrêmement rares en C++ :
        - à ma connaissance, la seule utilité de malloc() est de
permettre la création de son propre opérateur new, ce qu'on ne fait
pas tous les jours ;    
        - les histoires de '', c'est la cuisine interne de
std::string, et a priori, ce n'est pas toi (ni moi) qui l'écris.



Oui, tu auras deviné que j'avais le C en tête lorsque j'ai écrit
cela...


As-tu rencontré un exemple dans la vraie vie ?


ça m'est arrivé de mettre plusieurs jours à trouver un bug dans du
code que je n'ai pas écrit. Et lorsque le code fait 40k lignes, je ne
vais pas me lancer dans les tests unitaires. Et je pense que cette
situation est fréquente.

Je suis tout à fait d'accord que la méthodologie c'est tests
unitaires et compagnie, bonne parole prodiguée. Je suis aussi
d'accord que pour détecter tous les problèmes de deadlock et de
synchro, c'est pas l'idéal (mais là on s'éloigne du C++...). Et je
suis aussi d'accord que Valgrind aide beaucoup. Mais je ne négligerais
pas le débugger pour autant.

Pour moi gdb/ddd ne sont pas pratiques. Celui de Visual Studio l'est.

Dommage que le thread ait été dévié du sujet initial. j'aurais pens é
qu'il amuserait plus que ça. Je vous posterai ma trouvaille.

AG.
Avatar
James Kanze
On Nov 30, 2:15 pm, Marc Boyer
wrote:
Le 30-11-2009, AG a écrit :



[...]
Possible. J'utilisais le deboggeur avant, sous Win* il y a
plus de 10 ans, puis SunStudio puis ddd/gdb/xemacs, puis plus
rien...



Je travaille actuellement avec Visual Studios 8 ; il offre bien
moins de possibilités que gdb (ou au moins, je ne les ai pas
trouvé).

[...]
Non, tests unitaires / assert / printf, c'était la méthodologie.



À règle générale, dans des boîtes bien organisées, il est
interdit d'utiliser le deboggeur tant qu'on n'a pas de test
unitaire qui montre le problème. On ne veut pas qu'il
reapparaissent dans une version future, et on veut être sûr que
les tests unitaires le détectent. Et la plupart du temps, une
fois qu'on a isolé le problème assez pour définir un test
unitaire qui le declenche, on l'a isolé assez pour pouvoir
savoir exactement ce qui ne va pas d'après les symptomes.

On présentait gdb/ddd en illustration des cours sur
l'allocation dynamique, pour qu'ils "voient" leurs listes
chainées.



Et quand en projet ils galéraient à rechercher un bug, et
qu'ils finissaient par m'appeller, au bord de la crise,
parfois me montraient leur problème avec gdb/ddd, mais
toujours, j'allais à la pèche aux infos à coup
d'assert/printf, et, éventuellement valgrind.



Je ne suis pas sûr d'être d'accord avec l'utilisation du printf,
mais en général, il faut dire que si tu as besoin d'une
information une fois, tu en aurais besoin une autre fois, et
qu'il faut alors y introduire un log ou un trace. (Mais ça ne
vaut que pour les programmes « industriels » ; je vois mal un
élève, même à l'univerité, se servir extensivement des logs.)

--
James Kanze
Avatar
James Kanze
On Nov 30, 2:28 pm, "Senhon" wrote:
"AG" a écrit dans le message de groupe de discussion :




> On Nov 30, 2:27 pm, Marc Boyer
> wrote:



> Je pense que c'est grave effectivement. Tout ce que tu écris
> pour débugger est inutile avec un débugger. C'est donc un
> gain de temps immédiat. Ensuite d'aucun diront que leur
> debugger (type gdb) est mal pratique...peut être. Mais avec
> un débugger pratique, c'est un gain de temps certain.



Un debugger est un outils indispensable.



Pas tant que ça. Pour des poste-mortem, oui. Ou pour le code mal
écrit que tu hérites d'ailleurs. Où parfois dans des contextes
bien précis où tu ne peux pas utiliser des logs. Mais en
général, si la boîte est bien organisée, le déboggueur ser assez
peu.

Personnellement, je regretterai ( expérience déjà vécu )
amèrement, de ne pas disposer d'un debugger. Cela ne m'empêche
pas d'utiliser, aussi, des cout pour la mise au point. Les
deux se complémentent.

GDB, rend d'énormes services.
Mais, je n'ai rien trouvé de mieux que Visual Studio, c'est un
plaisir que de travailler avec cette merveille. GDB en
comparaison fait outil d'un autre âge.



Là, c'est de l'ironie, n'est-ce pas ? Parce que je me sers
actuellement de Visual Studio (pour comprendre du code que je
n'ai pas écrit, et pour lequel il n'y a aucune documentation),
et je me heurte constamment à ses limitations.

--
James Kanze
Avatar
AG
On Nov 30, 5:39 pm, James Kanze wrote:
Tu vas prétendre que la spécification des préconditions et des
invariants n'est pas nécessaire ? Qu'on peut se passer des tests
unitaires ?


Bonjour James,

Non bien sûr, mais à l'inverse vas-tu prétendre qu'on est à l'abri de
tout avec les tests unitaires ? Non bien évidemment. Si on débugge
sans débuggeur, c'est forcément que les tests unitaires ont loupé
quelque chose. Arrivé à ce stade, n'est-ce pas une perte de temps de
re-écrire plein de code de débug, pour finalement compléter les tests
unitaires qu'avec un cas supplémentaire ?

Aux élèves, il faudrait plutôt l'interdire. Il vaut mieux leur
apprendre d'écrire du code correctement, pourqu'ils n'en ont pas
besoin d'un déboggueur.


Ok, je prends bonne note, mais suis très surpris. C'était pas du tout
mon avis, et je tombe des nues.
Avatar
espie
In article ,
James Kanze wrote:
Aux élèves, il faudrait plutôt l'interdire. Il vaut mieux leur
apprendre d'écrire du code correctement, pourqu'ils n'en ont pas
besoin d'un déboggueur.



Avec ma population actuelle d'etudiants, je leur montre un debugger.
Il faut voir qu'ils n'ecrivent pas forcement du code correct, mais qu'ils
debugguent a grands coups de printf. Alors, quitte a debugguer, autant
que ca soit efficace...
Avatar
Fabien LE LEZ
On Mon, 30 Nov 2009 08:47:48 -0800 (PST), AG :

Oui, tu auras deviné que j'avais le C en tête lorsque j'ai écrit
cela...



Justement, le C et le C++ sont très différents. Il me semble donc
qu'il y aura d'importantes différences dans l'utilité d'un débogueur
ou un détecteur de fuites mémoire.

As-tu rencontré un exemple dans la vraie vie ?


ça m'est arrivé de mettre plusieurs jours à trouver un bug dans du
code que je n'ai pas écrit.



Je pense que tu as mis le doigt sur un point important : il y a pas
mal d'outils qui servent presque exclusivement sur le code des autres.

Celui de Visual Studio l'est.



Oui. Dommage qu'il faille subir, pour l'utiliser, le reste de l'IDE.

C'est d'ailleurs en partie pour ça que j'utilise peu le débogueur :
démarrer le débogueur me force à lancer l'IDE et à y créer un projet,
tâche désagréable à laquelle je ne me résoud que si je ne trouve pas
d'autre solution.
Avatar
Fabien LE LEZ
On Mon, 30 Nov 2009 18:17:42 +0000 (UTC), (Marc
Espie):

Avec ma population actuelle d'etudiants, je leur montre un debugger.
Il faut voir qu'ils n'ecrivent pas forcement du code correct, mais qu'ils
debugguent a grands coups de printf. Alors, quitte a debugguer, autant
que ca soit efficace...



Tu leur as déjà conseillé de s'orienter vers une autre voie, ou tu
attends un peu ?
Avatar
Senhon
"James Kanze" a écrit dans le message de groupe de
discussion :

On Nov 30, 2:28 pm, "Senhon" wrote:
"AG" a écrit dans le message de groupe de discussion :





GDB, rend d'énormes services.
Mais, je n'ai rien trouvé de mieux que Visual Studio, c'est un
plaisir que de travailler avec cette merveille. GDB en
comparaison fait outil d'un autre âge.



Là, c'est de l'ironie, n'est-ce pas ? Parce que je me sers
actuellement de Visual Studio (pour comprendre du code que je
n'ai pas écrit, et pour lequel il n'y a aucune documentation),
et je me heurte constamment à ses limitations.



Pas du tout, mais alors, loin de là.
Rien que l'usage de la touche F12, fonctionnalité que je n'ai rencontré
nulle part ailleurs, vaut le détour.
Bon c'est sûr que dans ton cas, c'est pas ton prog, peut-être pas ton OS de
prédilection, c'est pas ton outils de debug habituel, lorsque l'on est
habitué à une interface utilisateur, cela gêne pour passer à une autre : et
l'occurrence, entre GDB (commande ligne) et VisualStudio (graphique),
l'écart est déjà conceptuel.

Quelles sont ces limitations que tu rencontre ?
Avatar
Michael Doubez
On 30 nov, 17:39, James Kanze wrote:
On Nov 30, 1:43 pm, AG wrote:


{snip]
> Cela dit, qu'on me le dise si les debugger ne sont pas
> intensivement utilisés dans l'industrie, je serais content de
> me tromper.



Intensément, je n'ai pas l'impression. Colmme James Kanze je l'utilise
principalement dans 3 cas:
- post mortem (core dump)
- code mal écrit, logique pas claire ou trop d'indirection
- programme figé, attach pour localisation du point de blocage

Occasionnellement, en dernier recours pour un bug qui me mystifie. Il
m'arrive d'utiliser les printf (commentés ensuite) pour les parties de
programme qui génèreraient trop de log; c'est un patch sur le fait
qu'on a pas une granularité de log/trace infinie.

> Dans mon entourage, tout ceux à qui j'ai montré un
> debugger pratique l'ont adopté.
> PS: tes élèves, tu ne leur apprends pas le débugger ?

Aux élèves, il faudrait plutôt l'interdire. Il vaut mieux leur
apprendre d'écrire du code correctement, pourqu'ils n'en ont pas
besoin d'un déboggueur.



Ou mieux: leur apprendre à lire du code correctement. Ca leur
permettrait de se relire et de lire le code des autres. Ensuite le
debuggueur est dans la tête et ça va plus vite; puis AMA, en
identifiant les points clé d'un programme ou d'un algo, ils verraient
mieux quels tests unitaires écrire.

--
Michael
1 2 3 4 5