Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ - segmentation fault reading binary file

Tags:

c++

file

I got an issue, when I try to read char* professeur in a binary file it fails, giving me a segmentation fault in the read() function. What's weird is that for all other load function in other classes to read char* members works just fine but for this one, even if the professeur is written correctly in the I got a seg fault.

So here is the code:

Cours.h

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>

using namespace std;

#include "Liste.h"
#include "Event.h"
#include "Professeur.h"

class Cours: public Event
{
    private:
        char* professeur;
        Liste<int> groupes;
    public:
        void save(ofstream&) const;
        void load(ifstream&);
};

Cours.cpp

void Cours::save(ofstream& o) const
{
    int n=strlen(professeur);
    char buff[60], *buff2;

    o.write((char *)&n, sizeof(int));
    strcpy(buff, getProfesseur());
    o.write(buff, n+1);

    groupes.save(o);
    Event::save(o);
}

void Cours::load(ifstream& i)
{
    int n;
    char buff[60];

    i.read((char *)&n, sizeof(int));
    cout<<"n: "<<n<<endl;
    if(i.read(buff, n+1))//seg fault
    {
        strcpy(professeur, buff);
        cout<<"prof: "<<professeur<<endl;       
    }
    else
        cout<<"erreur read prof cours"<<endl;
    groupes.load(i);
    Event::load(i);
}
like image 374
Remi Hirtz Avatar asked Jan 10 '16 17:01

Remi Hirtz


2 Answers

n should be checked to make sure it doesn't get larger than the buffer.

In save():

int n=strlen(professeur);

n should be max 59 here - needs to be checked.

In load():

i.read((char *)&n, sizeof(int));

Better check n here too (max 59).

Also:

int n=strlen(professeur);
char buff[60], *buff2;

o.write((char *)&n, sizeof(int));
strcpy(buff, getProfesseur());
o.write(buff, n+1);

Two different values are used to write the data: strlen(professeur) and then getProfesseur().

You also don't allocate memory for professeur (at least not in the shown code). So strcpy(professeur, buff); in load() will fail too.

You might as well change:

private:
    char* professeur;

to

private:
    char professeur[60];

That way you don't have to allocate and deallocate memory yourself.

And make sure all strings are null-terminated.

Of course, if the exercise allows it, you can use string instead (string professeur;), and stream the data in and out using << and >>.

like image 57
Danny_ds Avatar answered Sep 30 '22 02:09

Danny_ds


First you read the length of the name. Allocat as many char as the name is long +1 for /0, right to target. Read from file to target and append \0 at the end:

void Cours::load(ifstream& i)
{
    int n;
    i.read((char *)&n, sizeof(int));
    cout<<"n: "<<n<<endl;
    if ( n <= 0 )
        return;

    professeur = new char[n+1];             // allocate professeur 
    if ( i.read( professeur, n ) )          // read directly to professeur
    {
        professeur[ n ] = ´\0`;             // write \0 at end of name
        cout<<"prof: "<<professeur<<endl;
    }
    else
    {
       delete [] professeur; 
       professeur = nullptr;
       cout<<"erreur read prof cours"<<endl;
    }

    groupes.load(i);
    Event::load(i);
}
like image 34
Rabbid76 Avatar answered Sep 30 '22 00:09

Rabbid76