2009-11-29 3 views
1

У меня есть небольшая проблема. Моя программа выдает ошибку сегментации при возврате нуля в main.ошибка сегментации в конце программы

Основная функция выглядит следующим образом:

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; 
} 

Закомментированного zomg часть является точкой, которая делает сбой программы. zomg указывает на char[20]. Моя точка в этой строке состоит в том, чтобы установить конец массива, потому что, если я не делаю этого, поток читает больше данных, чем 20 байтов, но он печатает только один ненужный символ.

Забавно, что даже если я напишу там дополнительный код между этим и возвратом 0, он сначала вызывает ошибку при возврате.

Только для случая вы хотели видеть класс 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; 
}; 

и 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! (извините, не смог удержаться) – aib

ответ

6

zomg [20] = 0 записывает один конец конца выделенного массива, но трудно догадаться, почему возникает segfault. Я предполагаю, что ваш умный компилятор использует alloca для выделения, и вы записываете на обратный адрес.

Возможно, было бы интересно посмотреть на сборку (обычно -S), чтобы увидеть, что происходит.

+0

thx много человек;) – Pyjong

5

Вы выделяете массив char[20], который имеет действительные индексы 0-19, но вы пытаетесь получить доступ к индексу 20. Это вызывает segfault.

+0

Да, вы разбиваете стек так, что, когда я думаю, что основная функция возвращает счетчик программ. Запустите его с Valgrind, и вы увидите. – MarkR

+0

, так как я могу закончить этот массив без установки последнего байта на ноль? – Pyjong

+0

@stupid_idiot - см. Мой ответ, вам нужно объявить, что ваш массив будет больше размера ваших данных. – ChrisF

1

Так что это немного здесь выделяется буфер с размером говорят 20:

new char[streamsize] 

Но вы пытаетесь добраться до 21-го символа:

buf[20] 

Существует вы SEG ошибку. Массивы равны нулю, поэтому для массива размером 20 индексы идут от 0 до 19.

1

Чтобы расширить ответ на int3, если ваши данные длиной 20 символов, вам нужно будет объявить массив длиной 21 символ так что вы можете «закончить его» с символом нулевого завершения. Если вы это сделаете, ваш код будет работать так, как zomg[20] будет действительной записью в массиве.

Смежные вопросы