2009-11-29 6 views
1

J'ai un peu de problème. Mon programme jette une erreur de segmentation en retournant zéro dans main.erreur de segmentation à la fin du programme

La fonction principale ressemble à ceci:

int main(int argc, char* argv[]){ 
    ifstream fs("test.dat", ios::binary); 
    cSendStream sendstr(&fs,20); 

    char *zomg=sendstr.data(); 
    //zomg[20]=0; 

    sendstr.read(20); 

    cout<<"Buffer: "<<sendstr.data()<<endl; 
    cout<<"Remaining: "<<sendstr.dataAvailable()<<endl; 

    sendstr.read(2); 
    cout<<"Buffer: "<<zomg<<endl; 
    cout<<"Remaining: "<<sendstr.dataAvailable()<<endl; 

    sendstr.read(10); 
    cout<<"Buffer: "<<zomg<<endl; 
    cout<<"Remaining: "<<sendstr.dataAvailable()<<endl; 
    cout<<"end..."<<endl; 
    return 0; 
} 

La partie a commenté zomg est le point qui rend le plantage du programme. zomg pointe sur char[20]. Mon point sur cette ligne est de définir la fin du tableau parce qu'en quelque sorte si je ne fais pas que le flux lit plus de données que 20 octets, mais il imprime un symbole inutile cependant. Ce qui est amusant est que même si j'écris il y a du code additionnel entre ceci et return 0 il renvoie la faute d'abord en revenant.

Juste pour le cas que vous vouliez voir la classe cSendStream:

cSendStream.h:

class cSendStream{ 
    public: 
    cSendStream(std::istream*, int streamsize); 
    int read(int); 
    int dataAvailable(); 
    char* data(); 
    private: 
    void shift(int); 

    std::istream *source; 
    int streamsize; 
    char* buffer; 
}; 

et cSendStream.cpp:

#include "cSendStream.h" 

cSendStream::cSendStream(std::istream *src, int size){ 
    source=src; 
    streamsize=size; 
    buffer=new char[streamsize]; 
    memset(buffer,0,streamsize); 
} 

int cSendStream::read(int i){ 
    if(dataAvailable()<1 || i<=0){ 
     return 0; 
    } 
    if(i>dataAvailable()){ 
     i=dataAvailable()-1; 
    } 
    if(i>streamsize){ 
     i=streamsize; 
    } 

    shift(i); 
    source->read(&(buffer[streamsize-i]),i); 
    return i; 
} 

int cSendStream::dataAvailable(){ 
    int current=source->tellg(); 
    source->seekg (0, std::ios::end); 
    int available = (int)(source->tellg())-current; 
    source->seekg (current); 

    return available; 
} 

char* cSendStream::data(){ 
    return buffer; 
} 

void cSendStream::shift(int i){ 
    char tmp[2048]; 
    memcpy(tmp,buffer,streamsize); 
    memcpy(&(buffer[0]),&(tmp[i]),streamsize-i); 
} 
+0

zomg! (désolé, n'a pas pu résister) – aib

Répondre

6

zomg [20] = 0 s'écrit au-delà de la fin du tableau alloué, mais il est difficile de deviner pourquoi la segfault se produit. Ma conjecture est que votre compilateur intelligent utilise alloca pour l'allocation et vous griffonnez sur l'adresse de retour.

Il peut être amusant de regarder l'assemblage (généralement -S) pour voir ce qui se passe.

+0

thx beaucoup d'homme;) – Pyjong

5

Vous allouez un tableau de char[20], qui a des index valides de 0-19, mais vous essayez d'accéder à l'index 20. Cela provoque le segfault.

+0

Oui, vous êtes en train de jeter la pile de sorte que quand le main retourne le compteur de programme est saccagé, j'imagine. Exécutez-le avec Valgrind et vous verrez. – MarkR

+0

alors comment terminer ce tableau sans mettre le dernier octet à zéro ?? – Pyjong

+0

@stupid_idiot - voir ma réponse, vous devez déclarer que votre tableau est plus grand que la taille de vos données. – ChrisF

1

donc ce bit ici alloué le tampon avec la taille 20 dire:

new char[streamsize] 

Mais alors vous essayez d'obtenir au 21 caractère:

buf[20] 

Il vous SEG faute. Les tableaux sont à zéro, donc pour un tableau de taille 20, les indices vont de 0 à 19.

1

Pour développer la réponse d'int3, si vos données sont de 20 caractères, vous devez déclarer un tableau de 21 caractères de sorte que vous pouvez "finir" avec le caractère de fin null. Si vous avez fait cela alors votre code fonctionnerait comme zomg[20] serait une entrée valide dans le tableau.

Questions connexes