| T.M. Sommers 2006-10-19, 1:21 pm |
| Wes wrote:
> I'm running FreeBSD 6.1 RELEASE #2. The program is writting in C++.
>
> The idea of the program is to open one file as input, read bytes from
> it, do some bitwise operations on the bytes, and then write them to
> this second file. However, when the second file is 15360 bytes long,
> the program dies with a "Segmentation Fault (core dumped)" error!
>
> I checked with gdb, and it says the last function to run was memcpy()
> from libc, which would explain the segmentation fault I think (the
> function was passed an invalid pointer maybe?).
>
> So how do I fix it? Below is the function's code:
>
> (please excuse the broken comments)
> ### BEGIN CODE ###
> int encFile(char* file)
> {
> ifstream::pos_type size;
> char* buffer = new char[32];
> char* ofile = new char[sizeof(file) + 4];
> char* tbuff = new char[32];
You should be using std::strings here. You should also not use
magic numbers; define constants for them.
> // First, we open our input and output files
> // We'll open them in binary mode (to prevent corruption), and
> with the
> // cursor at the end so we can see how big the input file is
> ifstream plain(file, ios::in|ios::binary|ios::ate);
> // Let's check to make sure it opened alright before
> continuing. If it
> // didn't, we better shut down.
> if(!plain.is_open())
> {
> cout << "Unable to open file '" << file
> << "'. Closing." << endl;
> return 0;
> }
> // So if we are here, it's open. We'll get its size and set
> our cursor at
> // the beginning.
> size = plain.tellg();
> plain.seekg(0, ios::beg);
> // Now! We need to create an output file. It will be the same
> as the
> // input filename, but with '.enc' tacked on the end. So first
> we copy
> // over the input filename
> for(int i = 0; i < sizeof(file); i++)
sizeof(file) is the size of a char pointer, not the length of the
string. If you don't want to use std::string, at least use
strncpy and strncat to manipulate char *-style strings.
> {
> ofile[i] = file[i];
> }
> // then tack on the '.enc'
> ofile[sizeof(file) + 1] = '.';
> ofile[sizeof(file) + 2] = 'e';
> ofile[sizeof(file) + 3] = 'n';
> ofile[sizeof(file) + 4] = 'c';
> // and then create the output file!
> ofstream enc(ofile, ios::out|ios::binary);
> // So now, we'll read 32 bytes at a time from the input file,
> send them to be
> // encrypted, and then drop the results into the output file.
> while(size - plain.tellg() > 32)
> {
> plain.read (buffer, 32);
> tbuff = Encrypt(buffer);
tbuff is a char *, and at the beginning of the function points to
an allocated block of memory. Each time the above line is
reached, that memory is leaked.
Whatever is going wrong (other than what has been mentioned) is
likely going wrong in the Encrypt function, which you did not show.
> enc.write(tbuff, 32); // this is where we die at 15360
> }
It would be simpler and more idiomatic to keep read()ing until
gcount != 32.
> // We now have some hanging bytes to get encrypted before we
> are finished.
> // We'll steal our 'size' variable since no one is using it
> anymore
> size = size - plain.tellg();
> plain.read(buffer, size);
> enc.write(Encrypt(buffer), size);
> // Our work here is done. Lets destroy everything and go home.
> plain.close();
> enc.close();
> delete buffer;
> delete ofile;
> return 0;
> }
> ### END CODE ###
>
> Any thoughts?
--
Thomas M. Sommers -- tms@nj.net -- AB2SB
|