Erreur avec free()

Résolu/Fermé
romanzo_cirminale - 21 sept. 2009 à 21:19
mamiemando Messages postés 33130 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 28 mai 2024 - 22 sept. 2009 à 22:32
Bonjour,

Voila j'ai cette erreur *** glibc detected *** ./SliceServer: free(): invalid next size (fast): 0x000000001dbf86d0 *** et apres plusieurs recherches je n'arrive pas a savoir d'ou elle vient, je pense qu'elle vient de ma boucle

while(line[j]!='"')
{
}

mais je ne comprend pas pourquoi.

Voici mon programme, je chercher a lire des donnees dans un fichier texte qui ressemble a ca:

Code : Txt

################################################
# ITK-SnAP Label Description File
# File format:
# IDX -R- -G- -B- -A-- VIS MSH LABEL
# Fields:
# IDX: Zero-based index
# -R-: Red color component (0..255)
# -G-: Green color component (0..255)
# -B-: Blue color component (0..255)
# -A-: Label transparency (0.00 .. 1.00)
# VIS: Label visibility (0 or 1)
# IDX: Label mesh visibility (0 or 1)
# LABEL: Label description
################################################
0 0 0 0 0 0 0 "Clear Label"
1 0 40 75 1 1 1 "M. quadriceps femoris"
2 50 123 28 1 1 1 "M. biceps femoris"
3 255 38 247 1 1 1 "M. semitendinosus"
4 140 93 215 0.89 1 1 "M. semimembranosus"
etc...



Le probleme se situe donc dans la lecture du LABEL et donc voici mon code
Code : C

string labelValue[80]; //variable globale

void GetRGBValue2()
{

int label=0;
char Red[3];
char Green[3];
char Blue[3];
char *labelName=NULL;
int i=0;
int j=0;
std:: ifstream fileLabel("/home/ImageViewer/LastViewer/built/Muscle labels.txt");
string line;

labelName=(char*)malloc(sizeof(char));
if(labelName==NULL)
{
exit(0);
}
char *l=labelName;


// read the label file and write in an array

if(fileLabel)
{


while(!fileLabel.eof())
{

std::getline( fileLabel, line );


if(line[0]!='#')
{

sscanf(line.c_str(),"%d %s %s %s ",&label,&Red,&Green,&Blue);



RGBValue[i][0]=Red;
RGBValue[i][1]=Green;
RGBValue[i][2]=Blue;

j=41;

while(line[j]!='"')
{


*l=line[j];
l++;
j++;

}


*l='\0';
labelValue[i]=labelName;

i++;

}
}
}



else
{
cerr<<"File not found"<<endl;
}

free(labelName);

}
A voir également:

4 réponses

mamiemando Messages postés 33130 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 28 mai 2024 7 755
22 sept. 2009 à 01:48
Bon déjà il y a un certains nombre de choses (outre l'indentation et le code à mon avis excessivement aéré) qui ne vont pas :

   labelName=(char*)malloc(sizeof(char));
    if(labelName==NULL)
    {
        exit(0);
    }


En écrivant ça, si une erreur d'allocation mémoire survient à ce malloc, tous les mallocs qui ont été faits précédemment et qui n'ont pas encore été libérés... ne sont pas libérés. Il faut donc sortir normalement de la fonction. En pratique sauf traitement exceptionnellement volumineux (et je doute que ce soit ton cas) un malloc n'échoue jamais, donc inutile de le contrôler.

sscanf(line.c_str(),"%d %s %s %s ",&label,&Red,&Green,&Blue);


... est à mon avis la source du problème car Red, Green, Blue ne peuvent stocker que deux caractères et le '\0'. Du coup pour une couleur à plus de trois chiffres (ce qui est assez fréquent vu que ca va de 0 à 255), tu as un débordement de plateau qui va a peu près tout planter. C'est d'autant plus dommage que tu pourrais utiliser une valeur numérique (et tu peux sans problème le faire dans un unsigned char (1 byte), même s'il paraît plus naturel d'utiliser ici un unsigned int (4 bytes)).

En admettant que ce soit ce que tu voulais faire, il faut remplir tes char avec ça :

unsigned char Red, Green, Blue; // ou unsigned int si tu préfères
...
sscanf(line.c_str(),"%d %d %d %d ",&label,&Red,&Green,&Blue);


Autre truc qui n'est pas génial, tu as du mettre dans ton code un "using namespace std;". Personnellement je te déconseille de le faire, c'est le meilleur moyen d'avoir des conflits de nom de types entre ton code et la STL. Ca force à écrire quelques std:: en plus je te l'accorde. Où à la rigueur tu mets un "using namespace std;" dans les fichiers .cpp mais jamais dans les .hpp.

Enfin il reste des soucis au niveau de la manière dont est gérée les pointeurs. Typiquement :

labelValue[i] = labelName; 


... qui dit "prend l'adresse de labelName, caste la en char, et écrit ce char en ième position dans labelValue".

De plus dans labelValue le '\0' terminal n'est jamais écrit, donc dès que tu vas lire ta chaîne, il va lire de la mémoire et ne s'arrêtera que si par miracle il croise une zone mémoire qui correspond à '\0' mais plus probablement, il y aura une erreur de segmentation).

Peut-être que tu devrais utiliser la classe std::string ou std::ostringstream, je pense que ça te simplifierait pas mal la vie.
https://community.hpe.com/t5/custom/page/page-id/HPPSocialUserSignonPage?redirectreason=permissiondenied&referer=https%3A%2F%2Fcommunity.hpe.com%2Ft5%2FServers-Systems-The-Right%2FSGI-com-Tech-Archive-Resources-now-retired%2Fba-p%2F6992583

Bonne chance
0
romanzo_cirminale
22 sept. 2009 à 17:07
Merci pour tout ces conseils, j'avoue que coder n'est pas forcement dur, mais bien coder est carrement plus difficile!

J'ai donc utiliser la classe string et c'est effectivement plus simple!

Sinon juste au passage je ne pense pas que tu puisse utiliser des %d pour des chars:

nsigned char Red, Green, Blue; // ou unsigned int si tu préfères
...
sscanf(line.c_str(),"%d %d %d %d ",&label,&Red,&Green,&Blue);


en tout cas ca ne marche pas. J'ai utilise des unsigned int c'estv rai que c'est plus simple.

Merci.
0
mamiemando Messages postés 33130 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 28 mai 2024 7 755
22 sept. 2009 à 21:37
Oui utilises des unsigned int. Est-ce que ton problème est résolu ?

Bonne chance
0
romanzo_cirminale
22 sept. 2009 à 21:58
ca marche niquel merci.
0
mamiemando Messages postés 33130 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 28 mai 2024 7 755
22 sept. 2009 à 22:32
parfait, je clos le sujet alors.

Bonne continuation !
0