tags:

views:

149

answers:

4

hey guys, i've got a bit problem. my program throws segmentation fault when returning zero in main

the main function looks like this

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

that commented zomg part is the point which makes the program crash.. zomg is pointing on char[20]. My point on that line is to set the end of the array because somehow if I don't do that the stream reads more data than 20 bytes, but it prints just one unnecessary symbol though.

funny thing is that even if i write there some additional code between this and return 0 it throws fault first when returning..

just for the case you wanted to see the cSendStream class:

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;

};

and the 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);
}
+5  A: 

You are allocating an array of char[20], which has valid indices of 0-19, but you are trying to access index 20. That is causing the segfault.

int3
Yes, you're trashing the stack so that when main returns the program counter gets trashed, I imagine.Run it with Valgrind and you'll see.
MarkR
how come? accessing zomg[20] shouldn't throw anything more but access violation :)))
stupid_idiot
so how do I end that array without setting the last byte to zero??
stupid_idiot
@stupid_idiot - see my answer, you need to declare your array to be one larger than the size of your data.
ChrisF
Allocate extra space for the null-terminator. I.e. if you want 20 'visible' characters, allocate a char[21] and set index 20 to '\0'.
int3
+1  A: 

So this bit here allocated the buffer with say size 20:

new char[streamsize]

But then you are trying to get to the 21st character:

buf[20]

There is you seg fault. The arrays are zero based so for an array of size 20 the indices go from 0 to 19.

Igor Zevaka
+1  A: 

To expand on int3's answer, if your data is 20 characters long you'll need to declare an array of 21 characters in length so that you can "finish it off" with the null termination character. If you did that then your code would work as zomg[20] would be a valid entry in the array.

ChrisF
+5  A: 

zomg[20]=0 is writing one past the end of the allocated array, but it is difficult to guess why the segfault is occurring. My guess is that your clever compiler is using alloca for the allocation and you are scribbling on the return address.

It might be fun to look at the assembly (usually -S) to see what's happening.

Richard Pennington
thx a lot man ;)
stupid_idiot