[C/C++] Défi: Trouvez les bogues ! (n°42)

Défi: Trouvez les bogues ! (n°42) [C/C++] - C++ - Programmation

Marsh Posté le 05-07-2002 à 02:02:46    

Je vous invite à un nouveau jeu:
Trouver le bogue dans un bout de code, ou proposer un tel code bogué.
 
J'apelle bogue toute erreur/mauvaise utilisation qui fait, ou peut faire, que le code ne compile pas, ne linke pas, ou que l'exécutable ne marche pas comme voulu.
Autrement dit, la palette est large...
 
C'est plus drôle si:

  • Le code est court.
  • L'erreur est subtile et tordue.
  • Le message d'erreur est incompréhensible. Mieux: pas de message d'erreur !
  • Le moment et le symptôme/message de cette erreur sont décrits. C'est plus rageant de ne pas comprendre avec toutes les clés !


Pour être plus clair, je propose:

  • De s'en tenir au langage+bibliothèques standards.
  • De ne pas mettre du code non-standard, car par définition il  peut générer des erreurs (a moins que ce ne soit délibéré bien sûr).
  • D'utiliser les mêmes titres gras et de numéroter les codes proposés, et d'utilisez ce numéro dans les réponses.
  • Que celui qui trouve le bogue explique le pourquoi du comment en détail.


Message édité par Musaran le 29-12-2002 à 05:16:35

---------------
Bricocheap: Montage de ventilo sur paté de mastic silicone
Reply

Marsh Posté le 05-07-2002 à 02:02:46   

Reply

Marsh Posté le 05-07-2002 à 02:03:41    

Liquidons tout de suite les archétypes...
[B]Erreurs de macros:[/B]

Code :
  1. #define PI = 3.141596 //erreur: "=" erroné
  2. double Var = PI*3 ; //Ce code...
  3. double Var = = 3.141596*3 ; //devient ceci! "syntax error : '='"
  4. #define PI 3.141596; //erreur: ";" erroné
  5. double Var = PI*3 ; //Ce code...
  6. double Var = 3.141596;*3 ; //devent ceci ! "illegal indirection"
  7. #define CARRE(a) a*a; //erreur: insuffisant
  8. int Var3 = CARRE(Var1+Var2) ;//Ce code...
  9. int Var3 = Var1+(Var2*Var1)+Var2 ;//équivaut à ceci !
  10. int Var3 = ~CARRE(Var1) ;//Ce code...
  11. int Var3 = (~Var1)*Var1 ;//équivaut à ceci !
  12. #define CARRE(a) ((a)*(a)); //corrigé


 
[B]Erreurs de syntaxe:[/B]

Code :
  1. char* ptr1, ptr2; //erreur: ptr2 est de type char
  2. char *ptr1, *ptr2; //solution1
  3. typedef char* charptr;
  4. charptr ptr1, ptr2;//solution2  
  5. if(Var=EOF) action(); //erreur: "=" au lieu de "=="
  6. if(EOF=Var) action(); //solution 1, mettre la constante devant provoque une erreur de compilation
  7. //solution 1, augmenter le niveau de warning
  8. if(/*test*/);
  9. /*action*/;
  10. while(/*test*/);
  11. /*action*/;
  12. for(/*init*/;/*test*/;/*++*/);
  13. /*action*/;
  14. //erreur: ";" termine l'instruction conditionelle sur une instruction nulle.
  15. //solutions:
  16. //-réindentation automatique (montre la faute en alignant /*action*/ avec le reste).
  17. //-augmenter le niveau de warning et mettre "NULL" quand on a vraiment une instruction nulle.
  18. switch (Var) {
  19. case 0: /*action*/; //erreur: manque "break"
  20. default: /*action*/;
  21. }
  22. //solutions:
  23. //-mettre le commentaire "//no break" quand c'est intentionnel.
  24. //augmenter le niveau de warning (ne marche pas partout).


 
[B]Erreurs de logique:[/B]

Code :
  1. int Var2 = Var1+1<<8; //erreur de précédence d'opérateur...
  2. int Var2 = Var1+(1<<8); //...équivaut à ceci (+256).
  3. int Var2 = (Var1+1)<<8; //solution: rendre explicite l'ordre si douteux, ou quand on mélange les types d'opérateurs.
  4. int Array[20];
  5. Array[20] = Var; //erreur: surpassement, tableau de 20 va de 0 à 19.
  6. Array[i]= i++; //erreur, i peut être incrémenté avant ou après l'indiçage.
  7. char* Msg = "Message";
  8. Msg[0]= 'm'; //erreur, les chaînes littérales sont des constantes !
  9. char* cptr = (char*)malloc(strlen(Msg)); //erreur: manque +1 au strlen pour le '\0' terminal.
  10. putchar("A" ); //erreur, "A" est une chaîne, 'A' est un caractère
  11. if(/*test1*/)
  12. if(/*test2*/){
  13.  /*action1*/;
  14. }; //ce ";" superflu termine le if imbriqué...
  15. else //...ce else concerne donc le premier if !
  16.  /*action2*/;


 
[B]Erreurs d'E/S:[/B]

Code :
  1. cVar = getchar();
  2. gets(cArray); //erreur: [Entrée] validant getchar est resté et donne une ligne vide
  3. while(getchar() != '\n'); //Solution, intercaller ceci pour vider le tampon
  4. fflush(stdin); //ceci est de comportement indéfini, à éviter !
  5. //idem avec la méthode C++
  6. cin >> cVar;
  7. cin.ignore(INT_MAX, '\n');
  8. cin.getline(cArray,cArraySize);


 
...et passons aux choses sérieuses !


Message édité par Musaran le 15-10-2002 à 00:23:07

---------------
Bricocheap: Montage de ventilo sur paté de mastic silicone
Reply

Marsh Posté le 05-07-2002 à 02:04:26    

Aller hop! J'ouvre le bal.
Celui-ci en a fait tourner en bourrique plus d'un, moi le premier.
[B]Trouvez le bogue !(1)[/B]

Code :
  1. class C{public:
  2. C()                     {} //constructeur sans arguments
  3. C(int)                  {} //constructeur
  4. C(const C& a)           {} //constructeur de recopie
  5. };
  6. C Var1();
  7. C Var2(3);
  8. C Var3(Var2);
  9. C Var2(Var1); //erreur de compilation: "cannot convert parameter 1 from 'class C (void)' to 'const class C &'"


Message édité par Musaran le 08-07-2002 à 02:29:01

---------------
Bricocheap: Montage de ventilo sur paté de mastic silicone
Reply

Marsh Posté le 05-07-2002 à 02:49:36    

bon allez à 3h du mat
je pense que Var1 n'est pas un objet mais la fonction C()
d'où le message

Reply

Marsh Posté le 05-07-2002 à 09:31:16    

Pareil, les parenthése après la déclaration de l'objet, y en faut pas lorsqu'on appel le constructeur par défaut. Il a interprété la déclaration de Var1 comme le proto d'une focntion.


---------------
Le Tyran
Reply

Marsh Posté le 05-07-2002 à 11:26:48    

est ce qu'on a le droit de declarer 2 fois Var2 dans la meme fonction ? :??:


---------------
LOVE & PEACE !!! [:kirvel]
Reply

Marsh Posté le 05-07-2002 à 11:28:38    

si c pas dans le même bloc ça peut passer:

Code :
  1. type Var2;
  2. if(...)
  3. {
  4.    type Var2;
  5. }


 
Ca ça doit passer, et encore pas avec tous les compilos


---------------
Le Tyran
Reply

Marsh Posté le 05-07-2002 à 11:50:15    

try58 a écrit a écrit :

est ce qu'on a le droit de declarer 2 fois Var2 dans la meme fonction ? :??:  




il s'est juste trompé, faut lire Var4

Reply

Marsh Posté le 06-07-2002 à 00:31:36    

Bien trouvé !
[B]Solution (1):[/B]

Code :
  1. C Var1(); //Déclaration d'une fonction Var1 sans arguments retournant un C.
  2. C Var1; //Création d'un objet Var1 de type C.

Voilà ce qui arrive quand on a une syntaxe aussi brève que le C++: des ambiguïtés !
 

ayachi a écrit a écrit :

il s'est juste trompé, faut lire Var4


Oui, j'avais pourtant fait attention, mais c'est vrai qu'a 3h...
 
Allez, suivant !
Celui-là est tordu... vraiment tordu !
[B]Trouvez le bogue !(2)[/B]

Code :
  1. char ch ;
  2. while( (ch = getchar()) != EOF) //erreur: risque de boucle infinie.
  3. /*action*/ ;


Message édité par Musaran le 08-07-2002 à 02:30:34

---------------
Bricocheap: Montage de ventilo sur paté de mastic silicone
Reply

Marsh Posté le 06-07-2002 à 01:58:36    

Code :
  1. #include <iostream>
  2. using namespace std;
  3. struct Toto {
  4.     virtual ~Toto() = 0;
  5.     virtual void print() { cout << "Toto:: print" << endl; }
  6. };
  7. Toto::~Toto() { cout << "delete Toto" << endl; }
  8. class Titi : public Toto {
  9. public:
  10.     virtual ~Titi() { cout << "delete Titi" << endl; }
  11.     void print() { cout << "Titi:: print" << endl; }
  12. };
  13. int main() {
  14.     Titi titi;
  15.     Toto *toto = &titi;
  16.     toto->print();
  17.     delete toto;
  18. }


 
Ca fait quoi ? (plusieurs réponses possibles)
 
- ca compile pas
- ca plante
- c'est pas ANSI C++
 
- ca affiche :
    Titi:: print
    delete Titi
    delete Toto
 
- ca affiche :
    Titi:: print
    delete Titi
 
- ca affiche :
    Titi:: print
    Toto:: print
    delete Titi
    delete Toto
 
- ca fait autre chose
 
réponse demain :)


Message édité par tanguy le 06-07-2002 à 01:59:41
Reply

Marsh Posté le 06-07-2002 à 01:58:36   

Reply

Marsh Posté le 06-07-2002 à 11:15:37    

Trouvez l'erreur :
 

Code :
  1. #include <iostream>
  2. int main()
  3. {
  4.    int i = 5;
  5.    for (int ì = 0; i < 10; i++)
  6.    {
  7.       std::cout << "Ligne : " << i << std::endl;
  8.    }
  9.    return 0;
  10. }


Message édité par Kristoph le 06-07-2002 à 11:16:20
Reply

Marsh Posté le 06-07-2002 à 11:18:12    

Kristoph a écrit a écrit :

Trouvez l'erreur :
 

Code :
  1. #include <iostream>
  2. int main()
  3. {
  4.    int i = 5;
  5.    for (int ì = 0; i < 10; i++)
  6.    {
  7.       std::cout << "Ligne : " << i << std::endl;
  8.    }
  9.    return 0;
  10. }






t'es sur que tu t'es pas trompé de "i" ? ;)


---------------
J'ai un string dans l'array (Paris Hilton)
Reply

Marsh Posté le 06-07-2002 à 11:38:12    

musaran a écrit a écrit :

Allez, suivant !
Celui-là est tordu... vraiment tordu !
[B]Trouvez le bogue ![/B]

Code :
  1. char ch ;
  2. while( (ch = getchar()) != EOF) //erreur: risque de boucle infinie.
  3. /*action*/ ;






Tu ne connais pas la valeur de EOF : ca pourrait tres bien etre -1.

Reply

Marsh Posté le 07-07-2002 à 04:09:21    

[B]tanguy (3):[/B]
Un destructeur virtuel pur ?
Je croyais pas que c'était permis, puisqu'un destructeur doit pouvoir être appelé.
Je suppose que c'est non-standard, ou que le standard n'a pas pensé à le préciser.
 
Quand à la définition d'une fonction virtuelle pure, je sais que c'est possible, mais à priori elle requiert un appel explicite "toto->Toto::~Toto()".
 
Toujours est-il que "delete toto" tente de libérer l'objet local "titi":

  • delete sur un objet pas alloué par new: comportement indéfini.
  • Dans le cas où ça marcherait quand même, titi sera redétruit à la fin de la fonction: comportement indéfini.

Voici la sortie:

Titi:: print

Après ça, c'est indéfini.Chez moi ça donne:

delete Titi
delete Toto

Puis erreur d'assertion.
 
[B]Kristoph (4):[/B]
Je pense que le i local au for va simplement masquer le i local à main.
Mais je ne peut pas vérifier parce que le compilo Microsoft ne considère pas i local au for.
 
 
R3g:
Sois plus clair si tu veux montrer que tu as compris !


Message édité par Musaran le 08-07-2002 à 02:31:35

---------------
Bricocheap: Montage de ventilo sur paté de mastic silicone
Reply

Marsh Posté le 07-07-2002 à 12:28:09    

Harkonnen a déjà troubé la réponse ( il me semble ), mais je pense que certains n'ont pas compris alors voilà la solution :
 
Le int i que j'ai définit dans le for n'est absolument pas la même variable que le i réelement utilisé. Celui de main c'est un i normal, celui du for, c'est un i avec un accent.
 
En fait, cet exemple doit pouvoir marcher même sur VC++ à supposer que votre compilo accepte les caractères ASCII étendus comme identifieurs de noms de variables. Je pense que ça marcherais mieux en Java quand même.

Reply

Marsh Posté le 07-07-2002 à 13:02:24    

musaran a écrit a écrit :

R3g:
Sois plus clair si tu veux montrer que tu as compris !



Ben EOF est une macro definie dans un fichier d'en-tete.
En faisant while( (ch = getchar()) != EOF) , on suppose que ch =getchar() renverra la valeur de EOF à la fin du fichier. Hors (je crois) getdhar() renvoie 0 si il aucun caractère n'est lu. Cette boucle est donc correcte, à condition que EOF vale 0. Mais EOF peut avoir une autre valeur, comme -1, et getchar() ne renverra jamais -1, d'où la boucle infinie.

Reply

Marsh Posté le 07-07-2002 à 13:14:22    

Moi je dirais plustot que getchar renvoie non pas un char mais un int et que EOF est défini justement comme étant une valeur ne tenant pas dans un char. Donc en affectant le resultat de getchar à un char, on ne sais plus si getchar a retourné EOF ou un charactère normal.

Reply

Marsh Posté le 07-07-2002 à 14:34:05    

musaran a écrit a écrit :

[B]tanguy:[/B]
Un destructeur virtuel pur ?
Je croyais pas que c'était permis, puisqu'un destructeur doit pouvoir être appelé.
 
justement ca n'empeche pas qu'il soit appelé
 
Je suppose que c'est non-standard, ou que le standard n'a pas pensé à le préciser.
 
c'est parfaitement standard et défini dans la norme
 
Quand à la définition d'une fonction virtuelle pure, je sais que c'est possible, mais à priori elle requiert un appel explicite "toto->Toto::~Toto()".
 
pour une méthode classique oui, mais pour un destructeur non (voir exeplication plus bas)
 
Toujours est-il que "delete toto" tente de libérer l'objet local "titi":

  • delete sur un objet pas alloué par new: comportement indéfini.
  • Dans le cas où ça marcherait quand même, titi sera redétruit à la fin de la fonction: comportement indéfini.


exact
 
Voici la sortie:

Titi:: print

Après ça, c'est indéfini.Chez moi ça donne:

delete Titi
delete Toto

Puis erreur d'assertion.




 
la réponse c'est :
 
Titi:: print
delete Titi
delete Toto
Segmentation fault
 
compilé avec gcc 2.95 et gcc 3.1 avec :
g++-3.1 test.cc -lstdc++ -ansi -Wall -Werror -pedantic
 
c'est du C++ parfaitement ANSI !
 
Si ca segfault c'est parceque avec delete toto on va supprimer la variable automatique titi et qui sera donc supprimer une deuxième fois automatiquement à la sortie du main.
j'ai mis un delete pour bien faire voir que l'on appellait le destructeur, faut pas se focaliser dessus, d'ailleurs j'aurais pas du le mettre, ca aurait évité que j'écrive 5 lignes pour me justifier lol
donc on peut enlever le delete toto et ca marchera parfaitement sans segfault.
 
 
 
bon alors les explications :
 
struct Toto
 
c'est comme une classe sauf que par défaut les données sont public au lieu d'être privé.
Il ne faut pas utiliser struct à la place de class parceque (il me semble) qu'en interne il y a des informations en moins. De toute facon c'était pour le fun ;) il faut toujours utiliser class.
 
virtual ca veut dire qu'en C++ que l'on veux mettre en place le polymorphisme, et tout le reste tient du polymorphisme.
 
virtual ~Toto() = 0 signifie que la méthode est virtuelle pure, donc que la classe Toto est abstraite (une interface) et ne peux pas être instancié.
En mettant = 0 on va imposer à celui qui dérive la classe Toto de surdéfinir le destructeur.
Si on n'avait pas mis = 0, dans la classe Titi on aurait pu omettre le destructeur.
 
voila la seule différence entre virtual et virtual = 0
 
le programme se comporterai de la meme facon si on avait juste écrit :
virtual ~Toto(); à la place de virtual ~Toto() = 0;
 
Ca affiche
Titi:: print
à cause du polymorphisme, ca c'est facile
 
 
et ca affiche :
delete Titi
delete Toto
également à cause du polymorphisme.
Il faut toujours appeller le destructeur du père, sinon on a une fuite mémoire : le descendant n'est pas correctement détruit.
d'ailleurs si on avait pas mis virtual devant le destructeur de Toto, le compilo affiche (meme cette bouze immonde de Visual C++) :
 
warning: `struct Toto' has virtual functions but non-virtual destructor
 
par contre pour une méthode classique en virtual pure, effectivement il faut l'appeler explicitement dans la classe fille. Mais le destructeur c'est un cas particulier comme le constructeur.
d'ailleurs pour s'en convaincre qu'il faut que le destructeur du père soit appeller il suffit de tracer les constrcteurs avec un cout :
on va s'apercevoir que le constructeur du père est systématiquement appellé en premier, puis ensuite celui du fils.
donc il est logique en retour que le destructeur du fils soit appelé en premier puis que le destructeur du père soit appellé.
pour cela il faut que le destructeur du père soit virtual.
 
par contre y'a un truc qui me choque et que je comprends pas très bien, c'est que l'on ne puisse pas écrire :
 
virtual ~Toto() = 0 { cout << "delete Toto" << endl; }
 
mais que l'on soit obliger d'écrire :
 
virtual ~Toto() = 0;
Toto::~Toto() { cout << "delete Toto" << endl; }
 
dernière précision :
= 0 ne signifie pas que l'on ne peut pas implémenter la méthode.


Message édité par tanguy le 07-07-2002 à 14:38:06
Reply

Marsh Posté le 07-07-2002 à 18:26:06    

Allez, encore une petite. Ca fait quoi ca ?
 


for(j=0; j<array_len; j+  =8)
{
   total += array[j+0 ];
   total += array[j+1 ];
   total += array[j+2 ]; /* Main body of
   total += array[j+3 ];  * loop is unrolled
   total += array[j+4 ];  * for greater speed.
   total += array[j+5 ];  */
   total += array[j+6 ];
   total += array[j+7 ];
}


Message édité par Kristoph le 07-07-2002 à 18:26:39
Reply

Marsh Posté le 07-07-2002 à 18:35:46    

Kristoph a écrit a écrit :

Allez, encore une petite. Ca fait quoi ca ?




 
Ca prouve a quel point la coloration syntaxique est utile.

Reply

Marsh Posté le 07-07-2002 à 18:48:04    

Kristoph a écrit a écrit :

Allez, encore une petite. Ca fait quoi ca ?
 


for(j=0; j<array_len; j+  =8)
{
   total += array[j+0 ];
   total += array[j+1 ];
   total += array[j+2 ]; /* Main body of
   total += array[j+3 ];  * loop is unrolled
   total += array[j+4 ];  * for greater speed.
   total += array[j+5 ];  */
   total += array[j+6 ];
   total += array[j+7 ];
}






Ca fait la somme du contenu d'un tableau (en supposant que ce soit pas un tableau de pointeurs, sinon ca fout la merde).

Reply

Marsh Posté le 07-07-2002 à 18:49:49    

R3g a écrit a écrit :

 
Ca fait la somme du contenu d'un tableau (en supposant que ce soit pas un tableau de pointeurs, sinon ca fout la merde).




 
regarde mieux le commentaire...

Reply

Marsh Posté le 07-07-2002 à 18:59:48    

lorill a écrit a écrit :

 
 
regarde mieux le commentaire...



Ah ouais, j'suis con :D
Mais en meme temps elle etait bien bien tordue celle-là !

Reply

Marsh Posté le 08-07-2002 à 00:30:44    

Code :
  1. void main()
  2. {
  3. double i;
  4. for (i = 0; i != 10; i += .3)
  5.    printf("%d\n", i);
  6. }


 
C pas dur ;)


---------------
WoIP - Video and Voice over IP -  http://www.woip.net/
Reply

Marsh Posté le 08-07-2002 à 02:20:32    

[B]Kristoph[/B] a trouvé le (2).
Quelle est la valeur de l'expression "ch = getchar()" ?
-Les spécifications du C moderne disent: la valeur de ch.
-Beaucoup d'implémentations utilisent le retour de getchar().
Donc ce code risque de marcher... alors qu'il ne devrait pas !
 
Concernant ta variable "ì", les caractères étendus ne font pas partie du standard C++. En Java si.
 
 

(3)tanguy a écrit a écrit :

par contre y'a un truc qui me choque et que je comprends pas très bien, c'est que l'on ne puisse pas écrire :
 
virtual ~Toto() = 0 { cout << "delete Toto" << endl; }
 
mais que l'on soit obliger d'écrire :
 
virtual ~Toto() = 0;
Toto::~Toto() { cout << "delete Toto" << endl; }
 
dernière précision :
= 0 ne signifie pas que l'on ne peut pas implémenter la méthode.



Parce que le =0 signifie justement qu'il n'y a pas de contenu.
Et puis ça serait une fonction virtuelle inline, ce qui n'est pas de la tarte.
Cela dit c'est accepté par VC++6.
On a vu qu'on peut quand même les définir, mais que cela requiert un appel explicite (précisément pleinement qualifié).
Le destructeur est donc un cas spécial, bénéficiant d'un appel explicite implicite.
 
Alors là je dis chapeau, ça c'est vraiment tordu.
Ça permet d'écrire un destructeur tout en obligeant une classe dérivée à en fournir un aussi.
 
Pourquoi pas mettre le destructeur private, pour rire un coup ?
 
 
[B](6)MrTonio[/B]:
"void main()" n'est pas standard, c'est "int main()" qui l'est.
A la rigeur, on peut omettre le "return" si le compilateur le permet.
 
Boucle infinie: i ne vaudra jamais exactement 10, puisque .3 n'est pas un tiers.
Cela reste vrai avec .333333333333333333 ou même 1.0/3.0, en raison de l'aproximation.
 
 
Un tout simple maintenant.
[B]Trouvez le bogue !(7)[/B]

Code :
  1. vector<vector<int>> VecVec ; //erreur de compilation


Message édité par Musaran le 08-07-2002 à 02:36:31

---------------
Bricocheap: Montage de ventilo sur paté de mastic silicone
Reply

Marsh Posté le 08-07-2002 à 21:46:02    

musaran a écrit a écrit :

 
Parce que le =0 signifie justement qu'il n'y a pas de contenu.
 
nan justement !
je l'ai dejà écrit, ca signifie simplement qu'il faut obligatoirement redéfinir la méthode dans la classe dérivé (donc la classe de base est abstraite). pas plus, pas moins

 
Et puis ça serait une fonction virtuelle inline, ce qui n'est pas de la tarte.
la méthode print() est virtuelle et ca ne lui pose aucun problème pour être aussi en inline
 
Cela dit c'est accepté par VC++6.
Visual C++ c'est le pire compilo C++ qui existe.
les personnes qui programment avec, pour moi ne font pas du C++ mais de la merde IMHO

 
On a vu qu'on peut quand même les définir, mais que cela requiert un appel explicite (précisément pleinement qualifié).
Le destructeur est donc un cas spécial, bénéficiant d'un appel explicite implicite.
 
ba oui, rien de spécial à ca, en C++ le polymorphisme c'est toujours comme ca : le destructeur du père est automatiquement appellé quand on lui ajoint virtual contrairement aux autres méthodes. En C++ le constructeur et le destructeur sont des cas particuliers (ils sont appellés automatiquement, crée automatiquement si on ne le fait pas etc...)
 
Alors là je dis chapeau, ça c'est vraiment tordu.
Ça permet d'écrire un destructeur tout en obligeant une classe dérivée à en fournir un aussi.
 
oui ;) ba c'est pas tordu ! en POO on utilise régulièrement des classes abstraites (interface). le destructeur virtuel pure c'est utilisé souvent, mais lui donner une implémentation par défaut beaucoup moins.
 
Pourquoi pas mettre le destructeur private, pour rire un coup ?
parceque ca compilera pas, donc c'est pas rigolo




Message édité par tanguy le 08-07-2002 à 21:47:39
Reply

Marsh Posté le 09-07-2002 à 01:58:31    

la méthode print() est virtuelle et ca ne lui pose aucun problème pour être aussi en inline
Ce que doit faire le compilateur n'est pas forcément clair. Une fonction virtuelle doit exister puisqu'elle a un pointeur dans la vtbl. Je suppose que seul un appel pleinement qualifié (Objet.Classe::methode()) sera effectivement inline.
Donc, je me disais que l'écriture "=0 {}" est peut-être évitée pour éviter l'ambigüité.
 
Visual C++ c'est le pire compilo C++ qui existe.
les personnes qui programment avec, pour moi ne font pas du C++ mais de la merde IMHO

Du code Windows ! (nuance très légère)
Quand je ferais qquechose de sérieux j'en changerait.
 
parceque ca compilera pas, donc c'est pas rigolo
Je pensais que l'erreur serait à l'endroit de la destruction.
Mais non, il vérifie le destructeur tout de suite.


Message édité par Musaran le 09-07-2002 à 01:59:07

---------------
Bricocheap: Montage de ventilo sur paté de mastic silicone
Reply

Marsh Posté le 09-07-2002 à 09:48:54    

Visual C++ c'est le pire compilo C++ qui existe.
les personnes qui programment avec, pour moi ne font pas du C++ mais de la merde IMHO

 
Je suis pas tout à fait d'accord. VC++, l'IDE, l'éditeur est très criticable, puisqu'il est destiner à produire du code windows, donc à priori plus du C que du C++, et qu'il a tous les defauts qu'un produit microsoft peut avoir. Ceci dit, pour faire du code windows rapidement et facilement, il est très adapté, et très performant (l'IDE, pas le code produit).
 
Quant au compilo lui-même, il est pas mauvais du tout, au contraire c'est sans doute un des meilleurs après le compilo Intel.


---------------
Au royaume des sourds, les borgnes sont sourds.
Reply

Marsh Posté le 09-07-2002 à 20:57:29    

R3g a écrit a écrit :

 

Quant au compilo lui-même, il est pas mauvais du tout, au contraire c'est sans doute un des meilleurs après le compilo Intel.





 
bon on va recopier ce que j'avais écrit ici :
http://forum.hardware.fr/forum2.ph [...] h=&subcat=
 

Citation :


les namespaces il aime pas, les templates pas beaucoup plus, il se vautre lamentablement sur les for  
en plus le niveau des warnings est pitoyable  
je crois que un compilo pire pour le C++ ca n'existe tout simplement pas !  
 
mais comme évidemment on va mettre ma parole en doute, fermons la parenthèse par les bonnes paroles de Bruce Eckel (que tout le monde connait évidemment) :  
http://www.mindview.net/Books/TICP [...] #Compilers  
 
A note about Visual C++.  
I periodically receive messages saying that the most recent version of Visual C++ will not compile many of the programs in the book.  
Let me attempt to be diplomatic here. Microsoft has stated that what they are creating is "a Windows compiler."  
Their interest is in creating a compiler that makes Windows programs, and not one that is compliant to the C++ Standard.  
As a result, the Standard C++ features in VC++ have been increasing at a relative crawl, and you should not expect VC++ to compile many of the programs in the book.  
The complete listing of files that will not compile can be found in the file CompilerData.txt in both volumes.  

 
et Thinking in C++ c'est vraiment pas un bouquin de C++ avancé :  
pas d'exception ni de STL à peine plus de template... c'est la base de chez base du C++  
 
bref n'écrivez pas que vous faites du C++ si vous utilisez Visual C++  


 
Reveillez-vous les gars, Microsoft c'est la première entreprise mondiale de logiciel avec des milliards de dollars !
ils sont meme pas foutu de faire un compilo qui supportent 2 boucles for d'affilées
faut pas déconner
n'importe quelle compilo C++ est supérieur à VC
 
que l'on soit obligé d'utiliser Visual C à cause de son boulot je veux bien, faut bien bouffer.
mais défendre cette bouze immonde, c'est de la connerie pure
 
Vous avez déjà utilisés des VRAIS outils pour la POO ?


Message édité par tanguy le 09-07-2002 à 20:58:25
Reply

Marsh Posté le 10-07-2002 à 09:50:55    

tanguy a écrit a écrit :

 
Vous avez déjà utilisés des VRAIS outils pour la POO ?




 
Xemacs + GCC, merci pour la convivialité!

Reply

Marsh Posté le 10-07-2002 à 10:42:50    

Euh, je voudrais pas critiquer, mais avez vous déja essayé VC++ 7 ?
 
Tous les défauts sus-mentionnés ont disparu comme par enchantement...


---------------
J'ai un string dans l'array (Paris Hilton)
Reply

Marsh Posté le 10-07-2002 à 21:09:41    

Harkonnen a écrit a écrit :

Euh, je voudrais pas critiquer, mais avez vous déja essayé VC++ 7 ?
Tous les défauts sus-mentionnés ont disparu comme par enchantement...




 
T'arrives à faire ca avec ton visual de merde ?
 
http://tanguy.dyndns.org/~tanguy/together3.gif
http://tanguy.dyndns.org/~tanguy/together1.gif
http://tanguy.dyndns.org/~tanguy/together2.gif
 
Et la version 7 elle supporte export, les string stream ?
on peut avoir des warnings (oui parceque pour le moment j'appelle meme pas ca des warnings) ?
Ca affiche autre chose que de l'assembleur quand on fait un trace de trop, ou il faut encore mettre un patch ?
 
Pour moi visual est une bouze et le restera, je vois pas pourquoi ca changerait (ils sont eu des années + plein de fric pour le faire).
Le seul truc qui fait jouir les blaireaux c'est la complétion de visual. Forcément quand on voit l'API du SDK, c'est tellement mal foutu que sans la complétion ca serait impossible à utiliser...
 
bon on va s'arreter là...
Je n'arriverais pas à convaincre quelqu'un que c'est de la merde et qu'il existe des produits 20x mieux, tant au niveau IDE que compilateur.

Reply

Marsh Posté le 10-07-2002 à 21:30:39    

J'ai déja  remarqué que ceux qui utilisent visual on commencé avec et n'ont jamais utilisé autre chose sans y etre forcé

Reply

Marsh Posté le 10-07-2002 à 21:31:08    

tanguy a écrit a écrit :

 
 
T'arrives à faire ca avec ton visual de merde ?
 
http://tanguy.dyndns.org/~tanguy/together3.gif
http://tanguy.dyndns.org/~tanguy/together1.gif
http://tanguy.dyndns.org/~tanguy/together2.gif
 
Et la version 7 elle supporte export, les string stream ?
on peut avoir des warnings (oui parceque pour le moment j'appelle meme pas ca des warnings) ?
Ca affiche autre chose que de l'assembleur quand on fait un trace de trop, ou il faut encore mettre un patch ?
 
Pour moi visual est une bouze et le restera, je vois pas pourquoi ca changerait (ils sont eu des années + plein de fric pour le faire).
Le seul truc qui fait jouir les blaireaux c'est la complétion de visual. Forcément quand on voit l'API du SDK, c'est tellement mal foutu que sans la complétion ca serait impossible à utiliser...
 
bon on va s'arreter là...
Je n'arriverais pas à convaincre quelqu'un que c'est de la merde et qu'il existe des produits 20x mieux, tant au niveau IDE que compilateur.
 




 
c fort joli mais pkoi est ce qu'on pourrait pas faire ca avec visu ?
 

Reply

Marsh Posté le 10-07-2002 à 21:36:39    

chrisbk a écrit a écrit :

c fort joli mais pkoi est ce qu'on pourrait pas faire ca avec visu ?


vc il peut pas tracer des lignes et carrés à la con :cry:

Reply

Marsh Posté le 10-07-2002 à 21:38:07    

youdontcare a écrit a écrit :

vc il peut pas tracer des lignes et carrés à la con :cry:  




 
 
pardon  ?

Reply

Marsh Posté le 11-07-2002 à 08:27:58    

Ouai enfin si c juste que tu peux pas faire de diagramme UML c pas top grave, Visual a des lacunes plus graves je trouve :D


---------------
Le Tyran
Reply

Marsh Posté le 11-07-2002 à 09:25:07    

Tanguy > t'as déja entendu parler de Visio ?
 

Citation :

J'ai déja  remarqué que ceux qui utilisent visual on commencé avec et n'ont jamais utilisé autre chose sans y etre forcé


 
Tout a fait ! J'ai commencé le C++ sous Windows avec Visual C++ 4, mais dans le cadre de mes loisirs.
Au boulot, j'utilise C++ Builder, mais j'y suis forcé.
 
VC++ a des défauts, c'est clair. Tous les IDE en ont. Mais le critiquer parce que c'est du Microsoft, la désolé mais je suis pas d'accord. Le VC++ 6 était buggé à mort, mais le .NET a bien rectifié le tir.


---------------
J'ai un string dans l'array (Paris Hilton)
Reply

Marsh Posté le 11-07-2002 à 13:14:06    

Harkonnen a écrit a écrit :

Tanguy > t'as déja entendu parler de Visio ?
 

Citation :

J'ai déja  remarqué que ceux qui utilisent visual on commencé avec et n'ont jamais utilisé autre chose sans y etre forcé


 
Tout a fait ! J'ai commencé le C++ sous Windows avec Visual C++ 4, mais dans le cadre de mes loisirs.
Au boulot, j'utilise C++ Builder, mais j'y suis forcé.
 
VC++ a des défauts, c'est clair. Tous les IDE en ont. Mais le critiquer parce que c'est du Microsoft, la désolé mais je suis pas d'accord. Le VC++ 6 était buggé à mort, mais le .NET a bien rectifié le tir.




 
 
Exact, meme la sp6 de vc me plante des fois encore a la gueule au moment de la compilation (il met 2 ans a sauvegarder un pauvre fichier, pis apres, prout). Le net corrige ces genres de conneries ?

Reply

Marsh Posté le 11-07-2002 à 14:11:39    

[

musaran a écrit a écrit :

[B]Kristoph[/B] a trouvé le (2).
Quelle est la valeur de l'expression "ch = getchar()" ?
-Les spécifications du C moderne disent: la valeur de ch.
-Beaucoup d'implémentations utilisent le retour de getchar().
Donc ce code risque de marcher... alors qu'il ne devrait pas !
 




Ben je dirais que c'est bon parce que:
dans le cas 1 : retour de la valeur de ch, ch etant definis comme
char et donc signe', et EOF = -1 donc la conversion est correct.
dans le cas 2: trivial !
 
en fait il aurait fallu declarer unsigned ch ... et la boucle infinie !
 
Plucker

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed