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 :

Problème de realloc


Sujet :

C++

  1. #1
    Membre averti
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2011
    Messages
    754
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2011
    Messages : 754
    Points : 376
    Points
    376
    Par défaut Problème de realloc
    Bonjour, j'ai un soucis avec mon realloc qui provoque visiblement une fuite mémoire avec un invalid next size.

    Mais je ne vois pas du tout le soucis dans le code..

    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
    int main(){
    	int buffsize=4;
    	int init_size=4;
    	int16_t * x=(int16_t*)malloc(buffsize*sizeof(int16_t));
    	int16_t i;
    	int bytesRead;
    	char *fi="test.wav";
    	FILE *fd_waveFile=NULL;
    	wavfile head_waveFile;
    	int cpt=0;
    	wavRead(&fd_waveFile,fi,&head_waveFile);
     
    	while ((bytesRead = fread(&i, sizeof(int16_t),1, fd_waveFile)) > 0){
    		if(cpt==(buffsize-1)){
    			x=(int16_t*)realloc(x,init_size*sizeof(int16_t));
    			buffsize=buffsize+init_size;
    		}
    		x[cpt]=i,
     		cpt++;
    	}
    return(0);
    }
    L'erreur:

    *** glibc detected *** ./test:realloc: invalid next size : une adresse mémoire

    suivi d'une bonne vingtaine de ligne de bactrace.

  2. #2
    Invité
    Invité(e)
    Par défaut
    C'est du C non?
    fd_waveFile c'est un pointeur de fichier? a quoi sert "wavRead(&fd_waveFile,fi,&head_waveFile);", parce que si c'est une fonction qui permet de lire entete wav du fichier pointer par "fd_waveFile", il y-a un soucis puisque fd_waveFile == NULL. Donc il n-'y a aucun fichier ouvert.
    Dernière modification par Invité ; 15/11/2016 à 09h07.

  3. #3
    Membre averti
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2011
    Messages
    754
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2011
    Messages : 754
    Points : 376
    Points
    376
    Par défaut
    Non c'est bien du c++;

    et l'argument qui te dérange est un argument en sortie c'est donc normal qu'il ait cette forme là.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    void wavRead(FILE **p_wav, char *filename, wavfile *p_header) {
    	//fopen_s(p_wav, filename, "rb"); //Windows version
    	*p_wav = fopen(filename, "rb");
    	if (*p_wav == NULL) {
    		fprintf(stderr, "Can't open input file %s\n", filename);
    		exit(1);
     
    ......
    	}

    Par contre là mon erreur a évolué et ne vient plus du realloc j'ai une segfault avant

    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
    int main(){
    	int init_size=2000;
    	int buffsize=init_size*sizeof(int16_t); //4 000
    	int16_t * x=(int16_t*)malloc(init_size*sizeof(int16_t));
    	int16_t i;
    	int bytesRead;
    	char *fi="test.wav";
     
     
    	FILE *fd_waveFile=NULL;
    	wavfile head_waveFile;
    	int cpt=0;
    	wavRead(&fd_waveFile,fi,&head_waveFile);
     
    	while ((bytesRead = fread(&i, sizeof(i),1, fd_waveFile)) > 0){
    		if(cpt==(buffsize)){
    			//x=(int16_t*)realloc(x,init_size*sizeof(int16_t)); j'ai commenté ça pour tester
    			buffsize=buffsize+init_size*sizeof(int16_t);
    		}
    		x[cpt]=i,
     		std::cout << "cpt=" << cpt << std::endl;
    		std::cout << "buffsize=" << buffsize << std::endl;
    		cpt++;
    	}
    return(0);
    }
    On sort avec une seg fault avec

    buff size=4000
    cpt=2013

  4. #4
    Invité
    Invité(e)
    Par défaut
    a la ligne 15, si tu remplacer :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    x=(int16_t*)realloc(x,init_size*sizeof(int16_t));
    par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    x=(int16_t*)realloc(x,buffsize*sizeof(int16_t));
    et a quoi te sert:

  5. #5
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut
    Que te dit valgrind ?

    Tu as des problèmes avec realloc et pourtant tu ne vérifies ni le retour de malloc(), ni celui de realloc(). Ce n'est peut-être pas ça, mais ce n'est néanmoins pas une bonne idée.

    Pourquoi réallouer avec init_size et non buffer_size ? Question inverse avec malloc().

  6. #6
    Membre averti
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2011
    Messages
    754
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2011
    Messages : 754
    Points : 376
    Points
    376
    Par défaut
    Citation Envoyé par Ratator Voir le message
    a la ligne 15, si tu remplacer :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    x=(int16_t*)realloc(x,init_size*sizeof(int16_t));
    par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    x=(int16_t*)realloc(x,buffsize*sizeof(int16_t));
    et a quoi te sert:
    Le problème ne vient plus de là étant donné que j'ai commenté le realloc et que je ne le fais pas.

    En outre, je préfère augmenter la taille de 4000 à chaque fois que de mettre au carré la taille...

  7. #7
    Invité
    Invité(e)
    Par défaut
    Tu fais x[cpt] = i et si cpt est >= init_size?

    int16_t * x=(int16_t*)malloc(init_size*sizeof(int16_t)); avec init_size = 2000

    Et sur ton erreur cpt == 2013

  8. #8
    Membre averti
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2011
    Messages
    754
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2011
    Messages : 754
    Points : 376
    Points
    376
    Par défaut
    Je simplifie le code pour montrer l'erreur.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    int16_t * x=(int16_t*)malloc(buffsize);
    	  if (x==NULL) exit (1);
    Ici, la taille du tableau buffsize est 4 000

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    while ((bytesRead = fread(&i, sizeof(i),1, fd_waveFile)) > 0){
    		x[cpt]=i,
     		std::cout << "cpt=" << cpt << std::endl;
    		std::cout << "buffsize=" << buffsize << std::endl;
    		cpt++;
    	}
    Ici cette boucle va fonctionner jusqu'à cpt=2013 avant de faire une erreur de segmentation.

    On est bien d'accord pour dire que 2013 < 4000 ?

    Mon tableau est donc suffisamment large pour contenir la donnée et ici cela n'explique pas l'erreur de segmentation.

  9. #9
    Invité
    Invité(e)
    Par défaut
    Essaye sa:
    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
    #include <string>
    #include <vector>
     
    int main(){
    	std::vector<int16_t> x;
    	int16_t i;
    	std::string fi = "test.wav";
    	FILE *fd_waveFile=NULL;
    	wavfile head_waveFile;
    	wavRead(&fd_waveFile,fi.data(),&head_waveFile);
    	while ( fread(&i, sizeof(int16_t),1, fd_waveFile) > 0){
                x.push_back( i);
    	}
        return(0);
    }

  10. #10
    Membre averti
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2011
    Messages
    754
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2011
    Messages : 754
    Points : 376
    Points
    376
    Par défaut
    Ton code ne compile pas. (en tout cas chez moi).

  11. #11
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par Amnael Voir le message
    Ton code ne compile pas. (en tout cas chez moi).
    Oublie pas d'inclure ton header contenant tes wav... focntions et rajoute std=c++11 aux options de compilation

    Tu peux aussi, faire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    wavRead(&fd_waveFile,fi.data(),&head_waveFile);
    if( fd_waveFile != nullptr)    {	
        while ( fread(&i, sizeof(int16_t),1, fd_waveFile) > 0){
            x.push_back( i);
        }
    }

  12. #12
    Expert confirmé
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Points : 4 182
    Points
    4 182
    Par défaut
    Citation Envoyé par Amnael Voir le message
    On est bien d'accord pour dire que 2013 < 4000 ?
    Ben oui. Mais pas pour affirmer que 2013 * sizeof(uint16_t) < 4000 .

    Citation Envoyé par Amnael Voir le message
    Mon tableau est donc suffisamment large pour contenir la donnée
    Ben non, l'opérateur [] n'adresse pas en octets mais en blocs de taille sizeof(uint16_t). Lorsque cpt == 2013 tu as donc déjà bien dépassé la borne haute de ton bloc mémoire car tu adresses à partir de l'octet 4026.

    Citation Envoyé par Amnael Voir le message
    et ici cela n'explique pas l'erreur de segmentation.
    Ben si.


    Une chose à prendre en compte lorsque l'on utilise realloc : on n'affecte jamais la valeur de retour de cet appel directement à la variable fournie en premier argument. Si l'opération foire, le bloc original est perdu (voir la page de man).

    D'une manière générale, utilise plutôt un std::vector comme on te le conseille.

  13. #13
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    En fait, en C++, on n'utilise jamais malloc, realloc, calloc et free.

    static_cast<T*>(malloc(sizeof(T))) se remplace avantageusement par new T(...), lui-même remplacé par make_unique<T>(...).
    static_cast<T*>(malloc(N*sizeof(T))) se remplace avantageusement par std::array<T, N>(), ou std::vector<T> (si le nombre réel d'éléments n'est pas connu).

    note: A la définition usuelle de jamais: "sauf si on a prouvé que c'est la meilleure solution".
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  14. #14
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Puisque tu prétends être en C++, pourquoi char*, alloc, realloc et non string et vector ?
    Si c'est juste pour avoir cout, c'est pas vraiment du C++. Utilise printf et fais du C ?
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

Discussions similaires

  1. Réponses: 13
    Dernier message: 21/03/2009, 20h49
  2. Problème avec realloc et struct
    Par _SamSoft_ dans le forum Bibliothèque standard
    Réponses: 38
    Dernier message: 27/12/2007, 10h13
  3. problème de realloc()
    Par daweed dans le forum C
    Réponses: 11
    Dernier message: 02/03/2007, 13h54
  4. [C, Realloc] problème de reallocation
    Par samtheh dans le forum C
    Réponses: 9
    Dernier message: 26/05/2006, 20h44
  5. Re-problème avec realloc() (désolé)
    Par Yabo dans le forum C
    Réponses: 8
    Dernier message: 30/07/2003, 22h07

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