Accueil
Accueil Le Club Delphi Kylix C C++ Java J2EE DotNET & C# Visual Basic Access Pascal Dev Web PHP ASP XML UML SQLSGBD Windows Linux Autres
logo

precedent    sommaire      


Mon programme plante ou se comporte bizarrement
auteur : Aurelien.Regat-Barrel
Parfois, on est confronté à des problèmes très étranges et apparemment sortis de nul part:

  • plantage Access Violation, core dump, null pointer
  • plantage ou erreur lors d'un appel à new ou à delete : DAMAGE: After Normal Block (#47), Heap block 3228a8 modified, Invalid Address specified to RtlFreeHeap
  • variables qui changent de valeur sans qu'on y ait touché
  • erreur lors d'une affectation, d'un passage de paramètres, d'une copie
  • contenu inattendu dans des tableaux

Ces disfonctionnement ont plusieurs causes possibles, mais ils sont généralement liés à une mauvaise utilisation de la mémoire. La première chose à faire est de compiler votre programme avec les options de débogage activées et de l'exécuter dans un débogueur afin que ce dernier vous emmène précisément à l'endroit où l'erreur est détectée (ce qui ne veut pas dire que c'est là qu'elle a lieu!).
Dans le cas d'un pointeur nul où d'une violation d'accès, il peut s'agir une erreur simple de programmation telle qu'un pointeur non initialisé. Si vous êtes confronté à une erreur d'apparence plus surnaturelle, vérifiez les points suivants:

  • les constructeurs par recopie de vos objets qui allouent des ressources
  • qu'il n'y a pas de débordement mémoire quelque part, en particulier à proximité de l'objet victimes de comportements étranges
  • que vos pointeurs sont correctement initialisés, et qu'ils ne pointent pas vers des données qui ont été libérées / détruites par la suite

soyez sûrs d'une chose : une variable ne change pas toute seule sans raisons de valeur. Cela est très souvent dû à un débordement qui vient écraser le contenu de votre variable. Vérifiez donc minutieusement l'utilisation que vous faîtes des pointeurs.
Un autre cas fréquent d'erreur est déclenché par les opérateurs et fonctions de gestion de la mémoire new, delete, malloc, free. Il faut savoir que ces derniers, en particulier en mode débogage, effectuent divers tests pour détecter toute mauvaise utilisation ou corruption de la mémoire. Si la vérification échoue, alors une erreur est signalée. Ce n'est donc pas ces opérateurs / fonctions qui sont en cause, mais bien votre code qui les utilise de manière erronée. En particulier, vérifiez bien que:

  • vous utilisez delete [] et non pas delete pour libérer des tableaux alloués avec new []
  • vous utilisez delete pour libérer une allocation faite avec new, et free pour malloc (ne pas mélanger les deux!)
  • que vous n'avez pas désalloué une ressource deux fois
  • que le pointeur retourné par new n'a pas été modifié ou altéré avant son passage à delete

Le message d'erreur vous aide généralement à déceler le problème. Si ce dernier parle de bloc corrompu ou modifié, alors il s'agit d'un débordement mémoire qui a écrasé les données internes ajoutées à proximité de votre allocation par la bibliothèque standard (afin de garder une trace de ce qui a été alloué, de faire des vérification, etc...).


Mon programme se lance et se termine immédiatement sans que je ne puisse rien voir
auteur : Aurelien.Regat-Barrel
Sous Windows, quand on lance un programme console depuis certains IDE (tel que devcpp), sa console n'est visible que durant son exécution. Si ce dernier ne fait qu'afficher un message, elle va donc disparaître immédiatement sans que l'on puisse lire quoique ce soit. Une solution simple consiste donc à attendre que l'utilisateur appuie sur la touche entrée avant de se terminer, comme dans l'exemple suivant:

#include <iostream> 
#include <limits> 

using namespace std;

int main()
{
    cout << "Hello World !\n";

    // attendre avant de quitter
    cin.ignore( numeric_limits<streamsize>::max(), '\n' );
}
La méthode utilisée pour effectuer cette attente est détaillée dans Comment faire une pause (attendre que l'utilisateur tape une touche) ?.


Mon programme C++ compile parfaitement avec gcc 2.x, et marque pleins d'erreurs avec gcc 3.x
auteur : Anomaly
La raison la plus probable est l'absence de la directive using namespace std;. Cette directive était optionnelle avec gcc 2.x (ceci était un défaut de conformité au standard). Il faut maintenant, avec gcc 3.x qui est conforme au standard, la mettre dans chaque fichier source, après le bloc des #include. Le programme ainsi modifié compilera aussi bien avec gcc 2.x que gcc 3.x.


Devcpp se plaint de ne pas connaître le format de mon .lib
auteur : Aurelien.Regat-Barrel
En ajoutant un fichier lib à la ligne de commande avec devcpp vous aurez l'erreur suivante :

file not recognized C:\Dev-Cpp\lib\glut32.lib File format not recognized

Cela est du au fait que le port de gcc fourni avec devcpp (MingW) utilise son propre type de fichiers lib portant l'extension .a. Il vous faut donc obtenir une version compatible avec devcpp de la bibliothèque que vous voulez utiliser.
Notez qu'un grand nombre d'entre-elles sont fournies dans le répertoire \lib, comme cela est le cas dans cet exemple avec libglut32.a. Regardez donc dans ce répertoire pour voir si l'équivalent de votre .lib ne s'y trouve pas.


Erreur "symbole externe non résolu _WinMain@16 référencé dans la fonction _WinMainCRTStartup"
auteur : Aurelien.Regat-Barrel
Si en compilant un programme C/C++ sous Windows vous obtenez un message d'erreur du type

error LNK2019: symbole externe non résolu _WinMain@16 référencé dans la fonction _WinMainCRTStartup [Linker error] undefined reference to `WinMain@16'

C'est que vous avez créé un projet Win32 sans console au lieu d'un projet console, ce qui fait que le compilateur s'attend à trouver la fonction d'entrée WinMain() à la place de la fonction standard main(). A partir de Visual C++ 7, vous pouvez modifier les propriétés de votre projet via Propriétés de configuation->Editeur de liens->Système->Sous-système : Console (/SUBSYSTEM:CONSOLE). Pour les versions antérieures, il faut créer un nouveau projet console.


Peut-on utiliser la bibliothèque boost avec Visual C++ ?
auteur : Aurelien.Regat-Barrel
Oui, mais de manière confortable à partir de Visual C++ 7.1 seulement (Visual C++ .Net 2003). Microsoft a consacré un article à ce sujet qui fait aussi office de bonne introduction à cette bibliothèque : en Boost for Visual C++ Developers.


La STL livrée avec Visual C++ 6 est bugguée !
auteur : Aurelien.Regat-Barrel
L'implémentation de la STL livrée avec Visual C++ 6 possède divers bugs. Il est vivement conseillé de procédé à sa mise à jour à partir du site de Dinkumware qui est l'auteur de cette implémentation. Pour cela, lire la page en Fixes for Library Bugs in VC++ V5.0/V6.0.


Erreur C1010 avec Visual C++
auteur : Aurelien.Regat-Barrel
"Fatal error C1010: unexpected end of file while looking for precompiled header directive" "Fatal error C1010: Fin de fichier inattendue lors de la recherche d'une directive d'en-tête précompilé"

Cette erreur survient quand votre projet est configuré pour utiliser un fichier d'en-tête précompilé (typiquement stdafx.h). Il vous suffit de désactiver l'utilisation des en-têtes précompilées dans les options C/C++ de votre projet.


J'ai un problème avec Visual C++ qui n'est pas traité ici
auteur : Aurelien.Regat-Barrel
Vous trouverez des solutions à divers problèmes spécifiques à Visual C++ dans la FAQ Visual C++.


Ma STL provoque des fuites mémoires ! Est-ce normal ?
auteur : Loulou24
Pas de panique, il se peut que ce soit normal. Si vous utilisez un outil de détection de fuites mémoires (par exemple en valgrind) sur ce programme, avec certains compilateurs (par exemple gcc) vous verrez un rapport indiquant de la mémoire non-libérée :

#include <string>
#include <iostream>

using namespace std;

int main()
{
    string s("hello world");
    cout << s << endl;
    return EXIT_SUCCESS;
}
LEAK SUMMARY:
    definitely lost: 0 bytes in 0 blocks.
    possibly lost:   0 bytes in 0 blocks.
    still reachable: 960 bytes in 1 blocks.
         suppressed: 0 bytes in 0 blocks.
Il ne s'agit pourtant pas de fuite mémoire mais d'une fonctionnalité de la bibliothèque standard. En effet, celle-ci peut posséder son propre espace d'allocation afin d'optimiser les performances, celui-ci n'étant pas libéré et rendu à l'OS une fois votre programme terminé. Mais pas de panique, la quantité de mémoire non libérée est constante et ne grossira jamais, peu importe le nombre d'objets que votre programme manipulera.

Toutefois, si cette fonctionnalité vous gêne vraiment vous pouvez la désactiver et forcer l'allocation "classique" :
- En définissant la macro __USE_MALLOC (gcc versions 2.91, 2.95, 3.0 et 3.1)
- En définissant la variable d'environnement GLIBCPP_FORCE_NEW (gcc versions 3.2.2 et supérieures)
- Si avez le goût du risque, vous pouvez également réécrire vos propres allocateurs

Cependant n'oubliez pas que ce comportement est un cas isolé, et que 99% des fuites mémoires seront dûes à des erreurs de votre part. Avant d'incriminer la bibliothèque standard, pensez à faire un maximum de tests !


La conversion de chaînes en majuscules / minuscules ne compile pas sous gcc
auteur : Loulou24
Ce code de conversion de chaînes en majuscules (et de la même manière en minuscules) ne compile pas avec gcc :

#include <string>    // inclut aussi <cctype> et donc toupper
#include <iostream>  // pour cout
#include <algorithm> // pour transform

int main()
{
    std::string s( "abcdef" ); 
    std::transform( s.begin(), s.end(), s.begin(), toupper ); 
    std::cout << s; // affiche "ABCDEF"
}

error : no matching function for call to `transform( __gnu_cxx::__normal_iterator<...>,
                                                     __gnu_cxx::__normal_iterator<...>,
                                                     __gnu_cxx::__normal_iterator<...>,
                                                     <unknown type> )`
Ce n'est pas un bug. Il existe en fait deux surcharges de std::toupper (et de std::tolower) : celle que l'on connaît bien prenant en paramètre le caractère à convertir, mais également une prenant en paramètre supplémentaire la locale à utiliser. Ainsi le compilateur ne sait tout simplement pas laquelle choisir.

Pour remédier à ce problème vous pouvez aider le compilateur à choisir la bonne surcharge :

std::transform( s.begin(), s.end(), s.begin(), static_cast<int (*)(int)>(toupper) );
Pour des informations supplémentaires vous pouvez consulter ce document : en "Quel est le type de toupper ?".


precedent    sommaire      

Consultez les autres F.A.Q's

Valid XHTML 1.1!Valid CSS!


Ce document issu de http://www.developpez.com est soumis à la licence GNU FDL traduit en français ici.
Permission vous est donnée de distribuer, modifier des copies de cette page tant que cette note apparaît clairement.
Certaines parties de ce document sont sous copyright Marshall Cline Les codes sources présentés sur cette page sont libres de droits, et vous pouvez les utiliser à votre convenance. Pour le reste, ce document constitue une oeuvre intellectuelle protégée par les droits d'auteurs. Ce document issu de http://www.developpez.com est soumis à trois licences, en fonction des contributeurs :
- Les contributions de Clément Cunin et LFE sont soumises aux termes de la la licence GNU FDL traduite en français ici. Permission vous est donnée de distribuer, modifier des copies des contributions de Clément Cunin et LFE tant que cette note apparaît clairement :
"Ce document issu de http://www.developpez.com est soumis à la licence GNU FDL traduite en français ici. Permission vous est donnée de distribuer, modifier des copies de cette page tant que cette note apparaît clairement".
- Les contributions de Marshall Cline sont sous copyright
- Pour ce qui est des autres contributions : Copyright © 2005 Developpez LLC : Tous droits réservés Developpez LLC. Aucune reproduction, ne peut en être faite sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'à 3 ans de prison et jusqu'à 300 000 E de dommages et intérêts. Cette page est déposée à la SACD.
Vos questions techniques : forum d'entraide Accueil - Publiez vos articles, tutoriels, cours et rejoignez-nous dans l'équipe de rédaction du club d'entraide des développeurs francophones. Nous contacter - Copyright 2000..2005 www.developpez.com