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 :

Assigner char * à un attribut fait planter le programme


Sujet :

C++

  1. #1
    Membre habitué
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Février 2009
    Messages
    141
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2009
    Messages : 141
    Points : 195
    Points
    195
    Par défaut Assigner char * à un attribut fait planter le programme
    Bonjour,
    Dans le cadre d'une classe résultant d'un Hash (SHA256, MD5, etc) possédant trois informations (Nom du hash, Hash, Longueur du hash), j'ai un problème quand j'assigne un pointeur à un de mes attribut.

    Je n'ai jamais vraiment eu de problème avec ma classe, mais j'ai réparé le système qui hachait et depuis que lui fonctionne, la classe ne fonctionne plus.

    Le plus étrange est que cela vient juste de l'affectation de "new char[taille]" à un attribut m_hashName, l'allocation du new char[taille] ou simplement le calcul de la taille ne cause pas le problème.

    Par exemple je peux allouer une variable exactement comme pour l'allocation originale, et le programme crash si je l'affecte à l'attribut.

    Exemples :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    m_attribut = new char[taille]; // Plante
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    char *test = new char[taille]; // Ok, pas de souci
    m_attribut = test; // Plante
    Voici le code complet de la classe pour ceux qui veulent :
    HashString.h:
    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
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
     
    #ifndef UU_HASHSTRING_H_INCLUDED
    #define UU_HASHSTRING_H_INCLUDED
     
    #include <cstring>
    #include <iostream>
     
    namespace Ungine
    {
    	namespace Utils
    	{
    		class HashString
    		{
    			public:
    				HashString();
    				HashString(const char *hashName, const char *digest);
    				HashString(const HashString& hs);
    				~HashString();
     
    				bool IsValid() const;
     
    				const char *GetDigest() const;
    				const char *GetHashName() const;
    				unsigned int GetLength() const;
     
    				HashString& operator=(const HashString &hash);
    				bool operator==(const HashString &hash) const;
    				bool operator!=(const HashString &hash) const;
     
    			private:
    				char *m_digest;
    				char *m_hashName;
    				unsigned int m_length;
    		};
     
    		std::ostream& operator<<(std::ostream &out, HashString &string);
    	}
    }
    #endif // UU_HASHSTRING_H_INCLUDED
    HashString.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
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
     
    #include "HashString.h"
     
    namespace Ungine
    {
    	namespace Utils
    	{
    		HashString::HashString() :
    		m_digest(0),
    		m_hashName(0),
    		m_length(0)
    		{
    		}
     
    		HashString::HashString(const char *hashName, const char *digest)
    		{
    			m_hashName = new char[strlen(hashName)+1];
    			strcpy(m_hashName, hashName);
    			m_digest = new char[strlen(digest)+1];
    			strcpy(m_digest, digest);
    			m_length = strlen(digest);
    		}
     
    		HashString::HashString(const HashString& hs)
    		{
    			m_hashName = new char[strlen(hs.m_hashName)+1];
    			strcpy(m_hashName, hs.m_hashName);
    			m_digest = new char[strlen(hs.m_digest)+1];
    			strcpy(m_digest, hs.m_digest);
    			m_length = strlen(m_digest);
    		}
     
    		bool HashString::IsValid() const
    		{
    			return m_length > 0;
    		}
     
    		HashString::~HashString()
    		{
    			delete[] m_digest;
    			delete[] m_hashName;
    		}
     
    		const char *HashString::GetDigest() const
    		{
    			return m_digest;
    		}
     
    		const char *HashString::GetHashName() const
    		{
    			return m_hashName;
    		}
     
    		unsigned int HashString::GetLength() const
    		{
    			return m_length;
    		}
     
    		HashString& HashString::operator=(const HashString &hash)
    		{
    			delete[] m_hashName;
    			delete[] m_digest;
    			m_hashName = new char[strlen(hash.m_hashName)+1];
    			strcpy(m_hashName, hash.m_hashName);
    			m_digest = new char[strlen(hash.m_digest)+1];
    			strcpy(m_digest, hash.m_digest);
    			m_length = strlen(hash.m_digest);
    			return *this;
    		}
     
    		bool HashString::operator==(const HashString &hash) const
    		{
    			return strcmp(m_digest, hash.m_digest) && strcmp(m_hashName, hash.m_hashName);
    		}
     
    		bool HashString::operator!=(const HashString &hash) const
    		{
    			return !strcmp(m_digest, hash.m_digest) || !strcmp(m_hashName, hash.m_hashName);
    		}
    	}
    }
     
    std::ostream& operator<<(std::ostream& out, Ungine::Utils::HashString& string)
    {
    	out << string.GetDigest();
    	return out;
    }
    Qu'est-ce que j'ai fais de mal?

    Je précise que l'erreur intervient dans le constructeur "HashString::HashString(const char *hashName, const char *digest)"

    Merci d'avance

  2. #2
    Membre confirmé
    Inscrit en
    Août 2004
    Messages
    556
    Détails du profil
    Informations forums :
    Inscription : Août 2004
    Messages : 556
    Points : 588
    Points
    588
    Par défaut
    stp, utilises std::string.

  3. #3
    screetch
    Invité(e)
    Par défaut
    c'est lequel qui plante ?

  4. #4
    Membre habitué
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Février 2009
    Messages
    141
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2009
    Messages : 141
    Points : 195
    Points
    195
    Par défaut
    Non, c'est fait exprès que j'utilise les chaines de caractère du C, parce que mon programme utilise beaucoup de classe de chaine de caractère différentes.

    En attendant que la classe de chaine de caractère principale soit écrite, j'utilise des C-string, mais ce qui m'inquiète c'est que je risque de rencontrer ce problème avec cette classe aussi.

    Ah je précise que l'erreur intervient dans le constructeur qui reçoit deux const char*

  5. #5
    screetch
    Invité(e)
    Par défaut
    c'est peut etre le code qui appelle cette fonction qui est mauvais. Comment tu appelles ce constructeur ?

  6. #6
    Membre habitué
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Février 2009
    Messages
    141
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2009
    Messages : 141
    Points : 195
    Points
    195
    Par défaut
    Avec deux const char * valides (Peuvent être affichés, mesurés, copiés sans problème)

    De toute façon ça plante avant même d'utiliser les arguments

    EDIT : je viens de tester la classe dans un main, elle fonctionne sans problème

    Voila la méthode où elle est crée et où ça plante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    			HashString SHA256::End()
    			{
    				char buffer[UU_HASH_SHA256_DIGEST_LENGTH];
    				SHA256_Internal_End(buffer);
     
    				char *finalHash = new char[UU_HASH_SHA256_DIGEST_STRING_LENGTH];
    				strcpy(finalHash, buffer);
     
    				HashString final(UU_HASH_SHA256_NAME, finalHash);
     
    				delete[] finalHash;
    				return final;
    			}
    EDIT2 : Même en créant un HashString vide (Constructeur par défaut), ça plante sur l'initialisation de m_hashName :/

    L'erreur semble venir de ce bout de code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    				char buffer[UU_HASH_SHA256_DIGEST_LENGTH];
    				SHA256_Internal_End(buffer);
    Je ne comprend vraiment pas...

    EDIT 3 :
    J'ai encore modifié le code pour créer directement un pointeur
    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
    			HashString SHA256::End()
    			{
    				char *buffer = new char[UU_HASH_SHA256_DIGEST_LENGTH];
    				SHA256_Internal_End(buffer);
     
    				std::cout << buffer << std::endl;
     
    				//char *finalHash = new char[UU_HASH_SHA256_DIGEST_STRING_LENGTH];
    				//strcpy(finalHash, buffer);
     
    				HashString final;
     
    				//delete[] finalHash;
    				return final;
    			}
    Ce code fonctionne avec le debugger, mais plante en renvoyant une erreur quand je le lance normalement (Process terminated with status -1073741819 (0 minutes, 2 seconds)

    Pourquoi est-ce que le code fonctionne avec le debugger mais pas normalement?

  7. #7
    screetch
    Invité(e)
    Par défaut
    strlen(0) plante je crois, tu devrais faire attention a ca dans ta classe.
    un HashString initialisé par défaut met ses chamts chaine a 0, puis une copie va claculer strlen(0) ce qui peut faire crasher.

  8. #8
    Membre habitué
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Février 2009
    Messages
    141
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2009
    Messages : 141
    Points : 195
    Points
    195
    Par défaut
    Merci, ça va régler un des problème, l'autre est que maintenant le debugger fait fonctionner le programme et m'affiche le hash, et l'utilisation normale (sans debugger, même en mode debug) ne fonctionne pas

  9. #9
    screetch
    Invité(e)
    Par défaut
    c'est quoi le symptome ? "ne fonctionne pas" ce n'est pas suffisant pour trouver l'erreur

  10. #10
    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 : 50
    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 Lynix Voir le message
    Non, c'est fait exprès que j'utilise les chaines de caractère du C, parce que mon programme utilise beaucoup de classe de chaine de caractère différentes.

    En attendant que la classe de chaine de caractère principale soit écrite, j'utilise des C-string, mais ce qui m'inquiète c'est que je risque de rencontrer ce problème avec cette classe aussi.
    Je ne crois pas que ce soit une bonne idée.

    En attendant que la classe chaîne de caractère principale soit écrite (mais pourquoi en écrire une ? std::string pose problème ?), utilise quand même une classe qui gère l'allocation, peu importe laquelle, ça évitera les problèmes liés à l'écriture d'une version, même temporaire, à base de C-string, et le basculement sera probablement plus simple.

  11. #11
    screetch
    Invité(e)
    Par défaut
    [ame="http://en.wikipedia.org/wiki/Shotgun_debugging"]http://en.wikipedia.org/wiki/Shotgun_debugging[/ame]
    je ne suis pas fan de conseiller de changer de techno "en esperant que le probleme va disparaitre".

  12. #12
    Membre confirmé
    Inscrit en
    Août 2004
    Messages
    556
    Détails du profil
    Informations forums :
    Inscription : Août 2004
    Messages : 556
    Points : 588
    Points
    588
    Par défaut
    Citation Envoyé par screetch Voir le message
    http://en.wikipedia.org/wiki/Shotgun_debugging
    je ne suis pas fan de conseiller de changer de techno "en esperant que le probleme va disparaitre".
    Non mais là c'est pas du shotgun debugging, c'est simplement remplacer tout le code buggé par un code robuste, testé, de haut niveau.

    Rien qu'en apercevant le code, je suis sûr et certain que c'est un problème d'allocation quelque part ou de temporaire, bref un truc avec la mémoire quoi.

  13. #13
    screetch
    Invité(e)
    Par défaut
    Citation Envoyé par JulienDuSud Voir le message
    bref un truc avec la mémoire quoi.
    CQFD. personne ne comprend le problème

  14. #14
    Membre confirmé
    Inscrit en
    Août 2004
    Messages
    556
    Détails du profil
    Informations forums :
    Inscription : Août 2004
    Messages : 556
    Points : 588
    Points
    588
    Par défaut
    Citation Envoyé par screetch Voir le message
    CQFD. personne ne comprend le problème
    Non mais je vais être franc, je n'ai même pas lu son code, j'ai vu des const char * partout, un segfault, ça concerne les chaines de caractère. Pas b'soin de plus de détails.

    Alors oui, il existe (d'office) une solution à son problème en gardant les char*, mais je pense que le meilleur conseil qu'on puisse lui donner, c'est d'abandonner cette habitude d'utiliser char* "en attendant".

  15. #15
    screetch
    Invité(e)
    Par défaut
    c'est une très mauvaise chose de ne pas avoir lu le code et de prétendre avoir la solution.

  16. #16
    Membre expert Avatar de jabbounet
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Juin 2009
    Messages
    1 909
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49

    Informations professionnelles :
    Activité : Consultant informatique

    Informations forums :
    Inscription : Juin 2009
    Messages : 1 909
    Points : 3 284
    Points
    3 284
    Par défaut
    dans le code que tu met je vois
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    char *buffer = new char[UU_HASH_SHA256_DIGEST_LENGTH];
    es tu certain qu'il ne manque pas un +1 par exemple car toutes tes autres copie de chaines le font.

  17. #17
    Membre habitué
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Février 2009
    Messages
    141
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2009
    Messages : 141
    Points : 195
    Points
    195
    Par défaut
    Non, le +1 est déjà pris en compte dans le define

    Par contre je n'ai rien compris, j'ai changé d'ordinateur, et sans même voir besoin de recompiler, tout fonctionnait comme ça aurait toujours du l'être.

    Pour répondre à vos questions :

    std::string n'est pas suffisant, il n'y a pas assez de méthodes pour exécuter des instructions voulues, comme les regex, ou les hashs.
    Et visiblement, il n'y a pas de problème avec les char*, donc non je ne les laisserais pas de côté.

    Et puis pour JulienDuSud, c'est très gentil de me dire que le code est buggé sans l'avoir lu, mais dans ce cas, c'est l'ordinateur qui semblait avoir un problème avec mon code (Les deux ordinateurs sur lesquels j'ai testé sont identiques)

    Enfin bon, je reviendrais au prochain problème inexplicable, merci

  18. #18
    Membre expert Avatar de jabbounet
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Juin 2009
    Messages
    1 909
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49

    Informations professionnelles :
    Activité : Consultant informatique

    Informations forums :
    Inscription : Juin 2009
    Messages : 1 909
    Points : 3 284
    Points
    3 284
    Par défaut
    Citation Envoyé par Lynix Voir le message
    Non, le +1 est déjà pris en compte dans le define

    Par contre je n'ai rien compris, j'ai changé d'ordinateur, et sans même voir besoin de recompiler, tout fonctionnait comme ça aurait toujours du l'être.

    Pour répondre à vos questions :

    std::string n'est pas suffisant, il n'y a pas assez de méthodes pour exécuter des instructions voulues, comme les regex, ou les hashs.
    Et visiblement, il n'y a pas de problème avec les char*, donc non je ne les laisserais pas de côté.

    Et puis pour JulienDuSud, c'est très gentil de me dire que le code est buggé sans l'avoir lu, mais dans ce cas, c'est l'ordinateur qui semblait avoir un problème avec mon code (Les deux ordinateurs sur lesquels j'ai testé sont identiques)

    Enfin bon, je reviendrais au prochain problème inexplicable, merci
    problème de version de certaines librairies, tu peux utiliser la commande ldd sur ton exécutable/lib pour voir avec quels libs tu t'exécute.

  19. #19
    Membre régulier
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    70
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 70
    Points : 88
    Points
    88
    Par défaut
    Ton digest, c'est une chaîne de caractères en hexadécimal, ou c'est du binaire ? Si c'est du binaire, il contiendra des \0 donc ne peut être manipulé avec des strcpy.

    D'autre part pour qu'une chose comme ça plante :

    m_truc = ...

    il faut que this soit corrompu, ce qui peut être le résultat de tout un tas de choses (appel sur un pointeur invalide, buffer overflow dû à un strcpy sur une "chaîne" qui est en fait du binaire, etc)

  20. #20
    Membre habitué
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Février 2009
    Messages
    141
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2009
    Messages : 141
    Points : 195
    Points
    195
    Par défaut
    De l'hexadécimal, mais le problème à été "corrigé" simplement en changeant de pc, sans recompiler.

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

Discussions similaires

  1. C# Html Agility Pack fait planter le programme
    Par pascal4435 dans le forum C#
    Réponses: 7
    Dernier message: 01/03/2013, 13h55
  2. push_back fait planter le programme
    Par vbaddict44 dans le forum C++
    Réponses: 54
    Dernier message: 04/06/2012, 17h30
  3. Réponses: 3
    Dernier message: 01/03/2009, 18h09
  4. Réponses: 2
    Dernier message: 17/03/2007, 13h43
  5. Réponses: 1
    Dernier message: 08/06/2006, 11h01

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