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 :

manque de mémoire !?


Sujet :

C++

  1. #1
    Membre éclairé
    Avatar de exe2bin
    Profil pro
    Passionné de programmation
    Inscrit en
    Mars 2009
    Messages
    537
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Passionné de programmation

    Informations forums :
    Inscription : Mars 2009
    Messages : 537
    Billets dans le blog
    3
    Par défaut manque de mémoire !?
    bonjour tous,
    je désire ouvrir un bitmap pour affichage écran ; le problème c'est que
    l'allocation mémoire semble planter le programme :
    j'alloue plus de 232ko (c'est un ptit bitmap).
    Est-il possible d'allouer autant de mémoire et même plus ??
    PS: ma machine tourne sur vista avec 4Go de RAM.

  2. #2
    Membre Expert Avatar de Ehonn
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2012
    Messages
    788
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2012
    Messages : 788
    Par défaut
    Normalement, il ne devrait pas avoir de problème avec l'allocation dynamique.
    Quelle est l'erreur affichée ? Comment fais-tu l'allocation mémoire ?

  3. #3
    Membre éclairé
    Avatar de exe2bin
    Profil pro
    Passionné de programmation
    Inscrit en
    Mars 2009
    Messages
    537
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Passionné de programmation

    Informations forums :
    Inscription : Mars 2009
    Messages : 537
    Billets dans le blog
    3
    Par défaut
    Ok , en premier lieu j'ouvre un ifstream :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ifstream in.open(nom_de_fichier_bmp,ios::binary;
    - Ensuite je lis les 2 premières structures du fichier :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    BITMAPFILEHEADER bfh;
    BITMAPINFOHEADER bih;
    .....
    .....
    in.read((char*) &bfh,sizeof(BITMAPFILEHEADER));
    in.read((char*) &bih,sizeof(BITMAPINFOHEADER));
    jusque la tout va bien car les structures contiennent les bonnes informations.
    ça se complique avec l'obtention des octets du bitmap car il faut d'abord savoir si celui ci contient une table des couleurs mais bref ...
    - j'initialise un pointeur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    LPSTR lpstrBitmap;
    ....
    ....
    lpstrBitmap = new char[nb_octets_du_bitmap]
    in.read((char) lpstrBitmap,nb_octets_du_bitmap);
    Le programme compile et s'execute mais le système ne reprend jamais la main !?

  4. #4
    Membre extrêmement actif

    Profil pro
    Inscrit en
    Février 2006
    Messages
    2 408
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 2 408
    Par défaut
    lpstrBitmap convertit en char? sans même aller plus loin, je dirai que y a un soucis ^^

  5. #5
    Membre chevronné

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2007
    Messages
    373
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Santé

    Informations forums :
    Inscription : Juin 2007
    Messages : 373
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    in.read((char) lpstrBitmap,nb_octets_du_bitmap);
    C'est une erreur de recopie, ou tu as oublié l'étoile dans (char*) ?

    Si ce n'est pas le cas, alors je te conseille d'essayer de reproduire ce phénomène avec le plus petit code possible, c'est à dire reprendre le code qui ne marche pas et créer un petit programme qui ne fait que ça. Si tu y arrives (le code devrait faire une 100aine de ligne), tu peux le poster ici en entier et on verra alors si quelque chose cloche. Car à part l'erreur que j'ai citée ci-dessus, je ne vois aucun problème avec le code que tu as posté jusqu'ici.

    Et pour répondre à ta question initiale, on peut allouer de très très gros tableaux en C ou C++. Tu peux essayer là aussi avec un petit programme de test pour voir quelle est la limite de ton système, car rien n'est imposé au niveau du C++. Le code devrait lancer une exception (du style bad_alloc) une fois que tu auras dépassé cette limite.

  6. #6
    Membre éclairé
    Avatar de exe2bin
    Profil pro
    Passionné de programmation
    Inscrit en
    Mars 2009
    Messages
    537
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Passionné de programmation

    Informations forums :
    Inscription : Mars 2009
    Messages : 537
    Billets dans le blog
    3
    Par défaut
    c'est juste une histoire de recopie. Je vais essayer ce que tu dis .
    Néanmoins je peux peut être essayer de récupérer l'erreur non ?!

  7. #7
    Membre chevronné

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2007
    Messages
    373
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Santé

    Informations forums :
    Inscription : Juin 2007
    Messages : 373
    Par défaut
    Tu peux essayer de lancer ton programme dans un debugger pour voir ce qu'il a à dire, oui. En général c'est ce qu'il faut faire quand on ne voit pas sois-même où est le problème

  8. #8
    Membre éclairé
    Avatar de exe2bin
    Profil pro
    Passionné de programmation
    Inscrit en
    Mars 2009
    Messages
    537
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Passionné de programmation

    Informations forums :
    Inscription : Mars 2009
    Messages : 537
    Billets dans le blog
    3
    Par défaut
    je travaille sur Code::Blocks et je n'ai jamais rien compris au debbuggers avec leurs messages sibylins ...

  9. #9
    Membre chevronné

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2007
    Messages
    373
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Santé

    Informations forums :
    Inscription : Juin 2007
    Messages : 373
    Par défaut
    Tu compiles (Ctrl-F9) avec les informations de debug (-g), puis tu lances le debugger (F8). Ton programme va se lancer tout seul, et s'arrêter à la ligne qui coince (s'il en est).

  10. #10
    Membre éclairé
    Avatar de exe2bin
    Profil pro
    Passionné de programmation
    Inscrit en
    Mars 2009
    Messages
    537
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Passionné de programmation

    Informations forums :
    Inscription : Mars 2009
    Messages : 537
    Billets dans le blog
    3
    Par défaut
    Désolé mec ; j"pige rien ; on me signale un "segmentation fault" alors que le programme n'est même pas commencé ....
    Je vais voir autre chose ,merci quand même.

  11. #11
    Membre éclairé
    Avatar de exe2bin
    Profil pro
    Passionné de programmation
    Inscrit en
    Mars 2009
    Messages
    537
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Passionné de programmation

    Informations forums :
    Inscription : Mars 2009
    Messages : 537
    Billets dans le blog
    3
    Par défaut
    Je crois avoir une piste alors je pose une question :
    Avoir comme donnée membre d'une classe un flux ,ouvert dans
    le constructeur et fermé dans le destructeur ,est-il susceptible de
    provoquer des disfonctionnements ?
    exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    class machin
    {
    private :
        ifstream  in;
    .......
    ........
    public :
        machin(string fileName) { in.open(fileName.c_str()); }
        ~machin() { in.close(); }
    ........
    .......
    };

  12. #12
    Membre chevronné

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2007
    Messages
    373
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Santé

    Informations forums :
    Inscription : Juin 2007
    Messages : 373
    Par défaut
    Citation Envoyé par exe2bin Voir le message
    Désolé mec ; j"pige rien ; on me signale un "segmentation fault" alors que le programme n'est même pas commencé ....
    Je vais voir autre chose ,merci quand même.
    Essayes de lancer gdb par ligne de commande :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    C:\> cd répertoire_où_se_trouve_ton_programme
    C:\répertoire_où_se_trouve_ton_programme> gdb ton_programme.exe
    blabla...
    Reading symbols from C:\répertoire_où_se_trouve_ton_programme\ton_programme.exe...done.   // <<-- ça doit s'afficher si tu as bien compilé ton code avec l'option -g
    (gdb) run
    blabla... SEGFAULT
    (gdb) bt
    Cela devrait t'afficher l'endroit où se situe l'erreur.

    Sinon pour répondre à ta dernière question : non, en soi ça ne pose aucun problème d'ouvrir et fermer un std::ifstream dans le constructeur et le destructeur.

    Avec les informations que tu as fournies jusqu'à maintenant, le problème peut être partout :
    1. Avant la lecture du fichier : tu as fait une bêtise ailleurs qui, par (mal)chance, n'a pas fait explosé ton programme jusqu'à présent, mais qui a silencieusement corrompu la mémoire. Ce n'est que maintenant que tu t'en prend plein les dents, mais ton code de lecture du bitmap est correct.
    2. Pendant la lecture du fichier. Je ne connais pas le format, mais le problème peut être :
      • Tu n'alloues pas correctement la mémoire dans laquelle tu veut lire le contenu du fichier.
      • Tu lis au bon endroit dans le fichier, mais pas la bonne taille. Autrement dit nb_octets_du_bitmap n'a pas la bonne valeur : il est soit non initialisé, soit mal lu dans le header du fichier, soit modifié involontairement.
      • Inversement, tu as la bonne taille, mais tu ne lis pas au bon endroit dans le fichier.
      • Autre piste : c'est le fichier qui est coupable (il faudrait essayer avec un autre, si possible qui provienne d'un endroit complètement différent : un site internet quelconque, ou différents logiciels de création d'images)
    3. Après la lecture du fichier : ton code de lecture du fichier est correct, mais le code qui utilise le bitmap est mauvais (fausses suppositions sur le contenu, mauvaise interprétation de la taille etc.).


    C'est pour ça qu'il faut que tu arrives à cerner le problème en décomposant clairement tes traitements 1, 2 et 3, puis en les testant de manière isolée.

    En dernier recours, compile avec tous les warnings possibles (-Wall). J'active toujours cette option personnellement. La grande majorité des warnings émis par gcc est utile.

  13. #13
    Membre éclairé
    Avatar de exe2bin
    Profil pro
    Passionné de programmation
    Inscrit en
    Mars 2009
    Messages
    537
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Passionné de programmation

    Informations forums :
    Inscription : Mars 2009
    Messages : 537
    Billets dans le blog
    3
    Par défaut
    je produit le code pour que chacun puisse le tester (et/ou le debboguer)
    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
    #ifndef	CMONBITMAP
    #define	CMONBITMAP
     
    const		int	MINI_INFO_HEADER_SIZE=16;
    const		int	FILE_HEADER_SIZE=14;
    const		int	RGBQUAD_SIZE=4;
     
    #include <windows.h>
    #include <iostream>
    #include <fstream>
    #include <string>
     
    //istream& operator>>(istream&,CMonBitmap&);
     
    using namespace std;
     
    class CMonBitmap {
    private :
    	BITMAPFILEHEADER	strctFileHeader;//
    	BITMAPINFOHEADER	strctInfoHeader;
    	LPSTR                       lpstrQuads;// pointeur sur la première structure RGBQUAD
    	LPSTR			            lpstrBitmap;// pointeur de début du bitmap
    	int				            uNBQuad;// nombre de structures RGBQUAD
    	ifstream		            inputFile;
     
    	void setFileHeader(void);
    	void setInfoHeader(void);
    	void setBitmap(void);
    public :
    	CMonBitmap(string);
    	~CMonBitmap();
    	int getNBColors(void) {return uNBQuad;}
    };
     
    #endif	// CMONBITMAP
    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
    88
    89
    90
    91
    92
    #include "bitmap.h"
     
    CMonBitmap::CMonBitmap(string fileName) {
    	inputFile.open(fileName.c_str(),ios::binary);// Ouverture du flux binaire
    	if(!inputFile)
    	{
    	    cout<<"Ouverture fichier "<<fileName<<" impossible."<<endl;
    	    exit(1);
    	}
    	setFileHeader();
    	setInfoHeader();
    	setBitmap();
    }
     
    CMonBitmap::~CMonBitmap() {
    	if(lpstrBitmap) delete[] lpstrBitmap;
    	if(lpstrQuads) delete[] lpstrQuads;
     
    	inputFile.close();
    }
     
    void CMonBitmap::setFileHeader(void) {
        cout<<"Entree dans setFileHeader"<<endl;
     
        inputFile.read((char*) &strctFileHeader,sizeof(BITMAPFILEHEADER));
     
        cout<<"Type : "<<strctFileHeader.bfType<<endl;
    	cout<<"Taille du fichier : "<<strctFileHeader.bfSize<<endl;
    	cout<<"Offset du debut du bitmap : "<<strctFileHeader.bfOffBits<<endl;
    }
     
    void CMonBitmap::setInfoHeader(void) {
        cout<<"Entree dans setInfoHeader"<<endl;
     
        inputFile.read((char*) &strctInfoHeader,sizeof(BITMAPINFOHEADER));
     
    	cout<<"Taille de la structure BITMAPINFOHEADER : "<<strctInfoHeader.biSize<<endl;
    	cout<<"Largeur/hauteur du bitmap : "<<strctInfoHeader.biWidth<<"/"<<strctInfoHeader.biHeight<<endl;
    	cout<<"Valeur de biClrUsed : "<<strctInfoHeader.biClrUsed<<endl;
    	cout<<"Valeur de biBitCount : "<<strctInfoHeader.biBitCount<<endl;
    }
     
    void CMonBitmap::setBitmap(void) {
        cout<<"Entree dans setBitmap"<<endl;
     
    	if(strctInfoHeader.biClrUsed == 0)
    	{
    		switch(strctInfoHeader.biBitCount)
    		{
    			case 1:
    				uNBQuad = 2;
    				break;
    			case 4:
    				uNBQuad = 16;
    				break;
    			case 8:
    				uNBQuad = 256;
    				break;
    			case 24:
    				uNBQuad = 0;
    				break;
    			default:	//erreur ?!?! (division par zéro)
    				uNBQuad = 1/(strctInfoHeader.biBitCount - strctInfoHeader.biBitCount);
    				break;
    		}
    	}
    	else if(strctInfoHeader.biClrUsed > 0) uNBQuad = strctInfoHeader.biClrUsed;
    	else 1/(strctInfoHeader.biBitCount - strctInfoHeader.biBitCount);	// erreur !?!? (division par zéro)
     
    	if(uNBQuad)
    		{
    		    long int nbOctets = uNBQuad*RGBQUAD_SIZE;
     
                lpstrQuads = new char[uNBQuad];
                inputFile.read((char*) lpstrQuads,nbOctets);
     
    		    cout<<"Taille de la table des couleurs : "<<nbOctets<<endl;
     
    		    nbOctets = strctFileHeader.bfSize - strctFileHeader.bfOffBits;
    		    cout<<"Taille du bitmap : "<<nbOctets<<endl;
    		    lpstrBitmap = new char[nbOctets];
    		    cout<<"adresse bitmap definie ..."<<endl;
    		    inputFile.read((char*) lpstrBitmap,nbOctets);
    		    cout<<"Allocation terminee ..."<<endl;
            }
    		else
    		{
    		    int nbOctets = strctFileHeader.bfSize - strctFileHeader.bfOffBits;
     
    		    cout<<"pas de table couleurs... "<<endl;
    		}
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    #include "bitmap.h"
     
    int main(void) {
        char    c;
    	CMonBitmap	bitmap("ce_que_vous_voulez.bmp");
     
    	cout<<"nombre de couleurs : "<<bitmap.getNBColors()<<endl;
    	cin>>c;
     
    	return 0;
    }

  14. #14
    Membre chevronné

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2007
    Messages
    373
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Santé

    Informations forums :
    Inscription : Juin 2007
    Messages : 373
    Par défaut
    Tu peux décrire exactement ce que ça fait chez toi, et ce que tu aurais attendu ?

  15. #15
    Membre éclairé
    Avatar de exe2bin
    Profil pro
    Passionné de programmation
    Inscrit en
    Mars 2009
    Messages
    537
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Passionné de programmation

    Informations forums :
    Inscription : Mars 2009
    Messages : 537
    Billets dans le blog
    3
    Par défaut
    c'est très simple :
    je lance le programme à partir de CodeBlocks ; la console s'ouvre et les détails du bitmap sont affichés et exact ,puis le programme attend l'entrée du caractère (cin>>c .
    Juste après la saisie et la validation (Entrée) apparait une boîte de dialogue bien connue de tous les développeurs sous Windows :
    "bitmap.exe a cessé de fonctionner ..." bla bla bla ; avec toujours les 2 même option : Rechercher ultérieurement une aide en ligne ......
    ou : Fermer le programme.
    Peut être le plus important est ce qui apparaît sur la console :
    process returned -1073741819 (0xc0000005)

  16. #16
    Membre chevronné

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2007
    Messages
    373
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Santé

    Informations forums :
    Inscription : Juin 2007
    Messages : 373
    Par défaut
    Ok je vois où est l'erreur. Ce n'est pas compliqué, mais ce serait bien que tu arrives à la trouver de toi même. En particulier, en apprenant à te servir du debugger.

    Il est peut être mal configuré dans ton Code::Blocks, donc on va passer par la ligne de commande pour cette fois (tu peux ouvrir un autre sujet si tu n'arrives pas à faire marcher gdb dans Code::Blocks).

    1. Pour simplifier les choses, mets bout à bout tout le code que tu viens de poster dans un seul fichier 'bmp.cpp' (dans l'ordre : bitmap.h, bitmap.cpp et main.cpp) et met le dans un endroit facile d'accès, par exemple sur la racine C:.
    2. Ouvre un invité de commande (Démarrer -> Executer -> cmd) et navigue jusqu'au dossier où tu as créé 'bmp.cpp' (avec cd).
    3. Compile ton programme avec les informations de debug :
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      > g++ -g bmp.cpp -o bmp.exe
    4. Lance gdb :
    5. Lance ton programme dans gdb :
    6. Ton programme s'exécute et demande d'entrer un caractère avant de se fermer (dans cet exemple j'ai pris un fichier BMP quelconque sur mon disque) :
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      Entree dans setFileHeader
      Type : 19778
      Taille du fichier : 289516
      Offset du debut du bitmap : 54
      Entree dans setInfoHeader
      Taille de la structure BITMAPINFOHEADER : 40
      Largeur/hauteur du bitmap : 273/353
      Valeur de biClrUsed : 0
      Valeur de biBitCount : 24
      Entree dans setBitmap
      pas de table couleurs...
      nombre de couleurs : 0
    7. Quand tu appuies sur Entrée pour confirmer, le debugger te dit qu'il a trouvé une erreur de segmentation (ton message sera sans doute un peu différent, vu que j'utilise Windows XP sur cette machine) :
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      Program received signal SIGSEGV, Segmentation fault.
      0x7c96fac1 in ntdll!RtlpNtMakeTemporaryKey () from C:\WINDOWS\system32\ntdll.dll
    8. Tu lui demande alors de tracer le chemin qui a conduit à cette erreur avec la commande backtrace (ou bt en abrégé) :
    9. Il t'affiche alors ligne par ligne toutes les fonctions qui ont mené à l'erreur. Chez moi ça donne :
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
      7
      8
      9
      #0  0x7c96fac1 in ntdll!RtlpNtMakeTemporaryKey () from C:\WINDOWS\system32\ntdll.dll
      #1  0x7c94bb44 in ntdll!LdrFindEntryForAddress () from C:\WINDOWS\system32\ntdll.dll
      #2  0x003e0000 in ?? ()
      #3  0x7c91b1ff in ntdll!RtlStartRXact () from C:\WINDOWS\system32\ntdll.dll
      #4  0x003e0000 in ?? ()
      #5  0x77c2c2de in msvcrt!free () from C:\WINDOWS\system32\msvcrt.dll
      #6  0x003e0000 in ?? ()
      #7  0x004014ba in CMonBitmap::~CMonBitmap (this=0x22fdf4, __in_chrg=<optimized out>) at bmp.cpp:45
      #8  0x00401a8b in _fu17___ZSt3cin () at bmp.cpp:130
    10. Là il faut apprendre à faire le tri, ligne par ligne. En commençant par #0 : tu vois que l'erreur s'est produite dans un appel système (dans ntdll.dll chez moi), dans une fonction obscure RtlpNtMakeTemporaryKey. Ça ne te parle pas, alors tu passes à la suivante jusqu'à ce que tu rencontres quelque chose de familier. Par exemple en #5 tu voit que ça provient en réalité d'un appel à free(), donc au niveau de la libération de la mémoire. Quelques lignes plus loin, en #7 c'est encore mieux : c'est ton code ! gdb te dit que l'erreur provient en réalité du destructeur de ta classe, défini dans bmp.cpp à la ligne 45. Chez moi, ça correspond à :
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
      CMonBitmap::~CMonBitmap() {
      	if(lpstrBitmap) delete[] lpstrBitmap; // << là
      	if(lpstrQuads) delete[] lpstrQuads;
       
      	inputFile.close();
      }
    11. Maintenant tu sais exactement où se produit l'erreur dans ton programme. Si tu réfléchis un peu aux différentes situations possibles et à ce qu'il peut arriver à lpstrBitmap, tu trouveras la vraie source du problème.

  17. #17
    Membre éclairé
    Avatar de exe2bin
    Profil pro
    Passionné de programmation
    Inscrit en
    Mars 2009
    Messages
    537
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Passionné de programmation

    Informations forums :
    Inscription : Mars 2009
    Messages : 537
    Billets dans le blog
    3
    Par défaut
    Merci beaucoup pour ces explications
    Il est vrai que je devrais m'intéresser aux outils de debogage ...
    Cela dit ,je me doutais bien que ça coinçait au niveau des pointeurs
    par rapport à l'execution mais aussi parce que ce sont des objets
    très imprédictibles par nature .
    Aussi je voudrais savoir qq chose :
    les numéros de ligne dans la sortie du debugger correspondent-ils à un ordre dans la transmission d'une exception ? et si oui cela voudrait-il signifier (en reprenant ton exemple de sortie) que l'erreur ce soit propagée de la ligne 8 jusque dans ntdll.dll (stoppant ainsi l'exécution du programme) ?

  18. #18
    Membre chevronné

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2007
    Messages
    373
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Santé

    Informations forums :
    Inscription : Juin 2007
    Messages : 373
    Par défaut
    Citation Envoyé par exe2bin Voir le message
    Cela dit ,je me doutais bien que ça coinçait au niveau des pointeurs
    par rapport à l'execution mais aussi parce que ce sont des objets
    très imprédictibles par nature .
    Les pointeurs sont très prédictibles au contraire. Ils ne font que ce que tu leur demande. Le vrai "souci" des pointeurs c'est qu'il y a très peu de vérifications qui sont faites par le compilateur (pour des raisons de performances et de généricité), ce qui fait qu'on peut facilement faire une bêtise (dans ton cas : oublier d'initialiser tes pointeurs à 0).
    Mais c'est aussi pour ça que le C++ fourni plusieurs classes qui permettent de n'avoir presque jamais à gérer la mémoire à la main.
    Dans ton cas, tu peux par exemple utiliser std::vector<char> :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    LPSTR lpstrQuads = nullptr;
    lpstrQuads = new char[nbQuads];
    inputFile.read((char*)lpstrQuads, nbQuads);
    delete[] lpstrQuads;
    C'est équivalent à :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    std::vector<char> lpstrQuads;
    lpstrQuads.resize(nbQuads);
    inputFile.read(lpstrQuads.data(), nbQuads);
    // Rien à "delete", c'est automatiquement fait dans le destructeur
    Ensuite quelques remarques :
    • Inutile de tester si le pointeur est valide avant d'appeler delete[]. On peut tout à fait appeler delete sur un pointeur nul, ça ne fait juste rien.
    • Tu as probablement un second bug dans ton programme : tu alloues lpstrQuads comme un tableau de nbQuads octets, mais tu lis nbQuads*RGBQUAD_SIZE octets du fichier ! Là tu corromps la mémoire.
    • Code : Sélectionner tout - Visualiser dans une fenêtre à part
      else 1/(strctInfoHeader.biBitCount - strctInfoHeader.biBitCount);	// erreur !?!? (division par zéro)
      C'est très moche... Tu devrais plutôt lancer explicitement une exception qui décrit le problème.


    Citation Envoyé par exe2bin Voir le message
    Aussi je voudrais savoir qq chose :
    les numéros de ligne dans la sortie du debugger correspondent-ils à un ordre dans la transmission d'une exception ? et si oui cela voudrait-il signifier (en reprenant ton exemple de sortie) que l'erreur ce soit propagée de la ligne 8 jusque dans ntdll.dll (stoppant ainsi l'exécution du programme) ?
    Ce n'est pas à proprement parler une exception, mais tu peux voir ça comme ça oui. La première ligne est là où la vraie erreur s'est produite (lire ou écrire dans de la mémoire qui sort de la zone allouée au processus, en particulier). Puis, de manière générale, la ligne #N indique la fonction qui a appelé la ligne #(N-1).

  19. #19
    Membre éclairé
    Avatar de exe2bin
    Profil pro
    Passionné de programmation
    Inscrit en
    Mars 2009
    Messages
    537
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Passionné de programmation

    Informations forums :
    Inscription : Mars 2009
    Messages : 537
    Billets dans le blog
    3
    Par défaut
    Citation :
    ce qui fait qu'on peut facilement faire une bêtise (dans ton cas : oublier d'initialiser tes pointeurs à 0).

    Il n'en est rien puisque le pointeur est initialisé plus tard :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    lpstrQuads = new char[nbQuads];
    Citation :
    Tu as probablement un second bug dans ton programme : tu alloues lpstrQuads comme un tableau de nbQuads octets, mais tu lis nbQuads*RGBQUAD_SIZE octets du fichier !

    Au contraire il n'y a probablement pas de bug puisque cela est fait
    pareillement avec les structures BITMAPFILEHEADER et BITMAPINFOHEADER !?
    De plus, comment faire autrement puisque la fonction de lecture du flux ne permet que la lecture de CHAR ??

  20. #20
    Membre Expert
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Par défaut
    Citation Envoyé par Kalith Voir le message
    1. Maintenant tu sais exactement où se produit l'erreur dans ton programme. Si tu réfléchis un peu aux différentes situations possibles et à ce qu'il peut arriver à lpstrBitmap, tu trouveras la vraie source du problème
    Bonne explication, je rajouterai juste que vérifier la valeur du pointeur qui pose problème donne tout de suite la solution :
    il est égal à 0xcccccccc, donc variable non initialisée. (Ces valeurs spéciales sont valables en debug avec Visual Studio, pour gcc, aucune idée, mais il y a probablement un équivalent)
    Citation Envoyé par exe2bin Voir le message
    Il n'en est rien puisque le pointeur est initialisé plus tard :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    lpstrQuads = new char[nbQuads];
    Cette ligne de code est dans un if, il suffit qu'on y passe pas (comme actuellement) et le pointeur n'est pas initialisé.

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Plantage sans doute par manque de mémoire
    Par verbose dans le forum Eclipse Java
    Réponses: 3
    Dernier message: 15/11/2007, 12h18
  2. Manque de Mémoire Virtuelle
    Par mayiba21 dans le forum Windows XP
    Réponses: 4
    Dernier message: 12/12/2006, 09h53
  3. [W2000 Pro] Manque de mémoire virtuelle empêche la connexion
    Par 2Eurocents dans le forum Windows Serveur
    Réponses: 2
    Dernier message: 30/11/2006, 20h20
  4. Manque de mémoire
    Par GO dans le forum C++
    Réponses: 1
    Dernier message: 25/09/2006, 16h30
  5. Manque de mémoire virtuelle sur Win2000 pro
    Par annedjomo dans le forum Windows Serveur
    Réponses: 7
    Dernier message: 02/03/2005, 10h16

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