IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++ Discussion :

Access violation sur une string


Sujet :

C++

  1. #1
    Membre du Club
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Août 2011
    Messages
    88
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur de jeux vidéo

    Informations forums :
    Inscription : Août 2011
    Messages : 88
    Points : 65
    Points
    65
    Par défaut Access violation sur une string
    Bonjour,

    Un problème un peu étrange qui vient de m'arriver et dont je n'arrive pas à me défaire :

    J'ai un objet d'une classe quelconque, avec une string comme attribut.
    Je n'ai pas besoin de remplir cette string tout de suite, je tiens à ce qu'elle reste vide avant de l'initialiser dans une méthode plus tard.
    Je considère, avec raison, que le constructeur de cette string sera appelé correctement et qu'un fois mon objet créé, son membre string sera lui aussi considéré comme correct.

    Seulement voilà, lorsque dans ma première méthode utilisée je fais !_str.empty() j'ai le droit a un magnifique crash avec erreur 0xC0000005.

    Et j'ai ce problème à chaque exécution.
    Comment ceci est-il possible ?

  2. #2
    screetch
    Invité(e)
    Par défaut
    poste ton code, sinon on ne peut pas t'aider.
    peut-être ton objet a été alloué et déjà desalloué?

    beaucoup de noms commencant par underscore sont reservés, il est préférable de les mettre a la fin.

  3. #3
    Membre du Club
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Août 2011
    Messages
    88
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur de jeux vidéo

    Informations forums :
    Inscription : Août 2011
    Messages : 88
    Points : 65
    Points
    65
    Par défaut
    Une petite rectification, quelque soit la façon dont je tente d’accéder à ma string, ça plante.

    Voici le code simplifié :
    .hpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    class X
    {
    	void handle_error (const system::error_code & e);
    	private:
    		string _auth_key;
    		bool connected;
    		/* ... */
    };
    .cpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    void X::handle_error (const system::error_code & e)
    {
    	switch (e.value())
    	{
    		case 10054: // Connexion coupée
    			/* ... */
    		break;
    		case 10061: // Connexion impossible
    			if (!connected && !_auth_key.empty()) // Voilà la ligne responsable du crash
    			{
    				/* ... */
    			}
    			else
    				/* ... */
    		break;
    		default:
    			/* ... */
    	}
    }
    je ne fais vraiment rien de particulier, et comble de l'étrangeté, il y a deux jour ce code marchait parfaitement.

  4. #4
    screetch
    Invité(e)
    Par défaut
    a priori je dirai donc que quelqu'un de mal intentionné (en toute probabilité, toi-même en fait) ecrase de la mémoire quelque part.

    Ce que je ferais donc, si tu as un bon debugger (visual studio) c'est de mettre un breakpoint mémoire; pour cela:
    * mets un breakpoint (normal) dans le constructeur de X
    * lorsque tu vas arriver a ce breakpoint, ajoute un "memory breakpoint"/breakpoint m´emoire sur "&_auth_key"
    * continues l'execution et le programme s'arrêtera de lui même a chaque fois que _auth_key est changée

  5. #5
    Membre du Club
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Août 2011
    Messages
    88
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur de jeux vidéo

    Informations forums :
    Inscription : Août 2011
    Messages : 88
    Points : 65
    Points
    65
    Par défaut
    Je travaille sous Code::Blocks malheureusement ...

    Autre chose que je viens de tester :

    Si je transforme la ligne comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if (!connected /*&& !_auth_key.empty()*/) // Voilà la ligne responsable du crash
    Le programme fonctionne sans problème !

  6. #6
    screetch
    Invité(e)
    Par défaut
    Code::Blocks a aussi des breakpoint mémoire je pense (Data breakpoint), le principe est exactement le même-
    bon sinon il y a la méthode de dichotomie, c'est plus long mais ca marche.
    ca consiste a ajouter le code _auth_key.empty(); partout partout, surtout dans des boucles et les méthodes appelées souvent, et voir quel est le premier qui pète. Tu sauras alors que l'erreur est intervenue entre le dernier _auth_key.empty() qui n'a pas explosé et celui qui vient d'exploser.

  7. #7
    Membre du Club
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Août 2011
    Messages
    88
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur de jeux vidéo

    Informations forums :
    Inscription : Août 2011
    Messages : 88
    Points : 65
    Points
    65
    Par défaut
    C'était une bonne idée, merci, ça m'a permis de voir que ce n'était pas la string qui posait problème ! Le code était beaucoup plus vicelard que ça :

    En fait dans mon else, j'utilisais une fonction d'affichage qui elle-même utilisait un équivalent de printf pour mettre en forme. Le problème, c'est que j'envoyais deux arguments pour le formatage alors qu'il n'en attendait qu'un seul !

    Voilà donc ce qui posait problème ... Il m'a suffit d'enlever l'argument de trop et tout ceci est rentré dans l'ordre.

  8. #8
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    La vraie parade consiste à ne pas utiliser de fonctions comme printf qui se comportent mal en cas d'erreur
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  9. #9
    Membre du Club
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Août 2011
    Messages
    88
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur de jeux vidéo

    Informations forums :
    Inscription : Août 2011
    Messages : 88
    Points : 65
    Points
    65
    Par défaut
    En fait, c'est une fonction d'affichage de ce type :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void print (const char * str, ...);
    C'est la seule solution que je connaisse pour formater ce que je veux dans une chaîne de caractère, tout en faisant d'autres vérifications dans le corps de la fonction bien entendu.

    C'est donc ma va_list qui me fait planter je crois.

  10. #10
    screetch
    Invité(e)
    Par défaut
    sous GCC il y a un moyen d'activer les warnings de formattage (donc de vérifier que les arguments seront corrects a la compilation)
    ainsi que de declarer une fonction "printf-like", pour que GCC applique aussi la verification a cette fonction

    http://www.unixwiz.net/techtips/gnu-...es.html#format
    et l'option -Wformat

  11. #11
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    Citation Envoyé par Nekkro Voir le message
    En fait, c'est une fonction d'affichage de ce type :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void print (const char * str, ...);
    C'est la seule solution que je connaisse pour formater ce que je veux dans une chaîne de caractère, tout en faisant d'autres vérifications dans le corps de la fonction bien entendu.

    C'est donc ma va_list qui me fait planter je crois.
    Jette un oeil sur boost.format :

    Boost.format enforces a number of rules on the usage of format objects. The format-string must obeys the syntax described above, the user must supply exactly the right number of arguments before outputting to the final destination, and if using modify_item or bind_arg, items and arguments index must not be out of range.
    When format detects that one of these rules is not satisfied, it raises a corresponding exception, so that the mistakes don't go unnoticed and unhandled.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  12. #12
    Membre émérite

    Inscrit en
    Mai 2008
    Messages
    1 014
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 1 014
    Points : 2 252
    Points
    2 252
    Par défaut
    Tiens ça me fait penser à l'excellent article de John Carmarck sur les analyseurs statiques de code.
    Dans cette article Carmack explique qu'il a finalement décidé de passer un coup d'analyseur statique sur l'ensemble de la codebase d'ID software et surprise !

    Citation Envoyé par John Carmarc
    Printf format string errors were the second biggest issue in our codebase
    J'avoue que je n'en reviens toujours pas.
    C'est amusant de voir que lorsque les gens évoquent les difficultés classiques du C, la discussion tourne toujours autour de la gestion manuelle de la mémoire, des dépassements de tableaux, de la gestion manuelle des string (char* + '\0'), ce genre de truc, mais personne ne s'attarde vraiment sur le danger de bête erreur de printf, qui pourtant formerait donc une des classes de bug la plus répandu !

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Problème Access Violation dans une classe
    Par randriano dans le forum C++Builder
    Réponses: 1
    Dernier message: 11/04/2007, 18h49
  2. Access violation sur un new
    Par cedekasme dans le forum C++Builder
    Réponses: 16
    Dernier message: 23/01/2007, 14h32
  3. binding sur une string
    Par fxp17 dans le forum JSF
    Réponses: 8
    Dernier message: 08/09/2006, 11h38
  4. [Access] Requête sur une table et tri sur une autre
    Par VooDooS dans le forum Langage SQL
    Réponses: 2
    Dernier message: 30/08/2006, 15h07
  5. [VB2003][ACCESS] Question sur une requete
    Par Kanie dans le forum Langage SQL
    Réponses: 3
    Dernier message: 30/03/2006, 17h25

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo