0

So basically I was writing a test program to see if I could write and read a vector of queues into a binary file using fwrite and fread respectively. Even though the reading and writing part is done correctly and the values are correct, I get a double free or corruption error. The test code is the following

#include <stdio.h>
#include <vector>
#include <queue>

int main(){

vector<queue<unsigned> > hello(17);
vector<queue<unsigned> > here(17);
queue<unsigned> temp;
for(int f=0;f<4;f++){//initialise a random queue
    temp.push(f);
}
for(int i=0;i<hello.size();i++){//assign random queue to every index of vector
    hello[i]= temp;
}
FILE *fo;
fo = fopen("hello","wb");
fwrite(&hello[0],sizeof(queue<unsigned>),hello.size(),fo);
fclose(fo);
printf("Writing done!\n");

FILE *fi;
fi=fopen("hello","rb");
fread(&here[0],sizeof(queue<unsigned>),here.size(),fi);
fclose(fi);
printf("Reading done!\n");
for(int i=0;i<here.size();i++){
    printf("At key %d value at front is is %d",i,here[i].front());
    here[i].pop();
    printf(" value %d ",here[i].front());
    here[i].pop();
    printf(" value %d\n",here[i].front());
}
} 

The error seems to be when doing the fread operation.

Grijesh Chauhan
  • 57,103
  • 20
  • 141
  • 208
Alex Oiko
  • 3
  • 1
  • You're probably writing out pointers to disk, and then reading them back in, and the system does not like that. If your structures contain pointers, you can't simply write them to disk and read them back in again; you need to 'linearize' or 'serialize' the structures, and then delinearize or deserialize them on input, taking care to do the appropriate allocation. That's a lot harder than just using `fread()` and `fwrite()`. – Jonathan Leffler Mar 30 '13 at 12:09

3 Answers3

1

fread and fwrite take a raw pointer as their first argument. In each case, what you've passed in is the address of a queue (the first element in the vector of queues named hello and the first element of the vector of queues named here.

What you are writing is the actual queue classes themselves, i.e. the class that contains the queue of elements you want to write. Depending on the implementation of queue, you could be writing anything (or not!). For example, if the queue class contains a pointer pointing to an array of elements, you are writing the value of a pointer, but not the elements themselves.

I would recommend serializing (Is it possible to serialize and deserialize a class in C++?) and deserializing your vector of queues.

Community
  • 1
  • 1
maditya
  • 8,626
  • 2
  • 28
  • 28
1

What you are doing is essentially equivalent to

memcpy(&here[0], &hello[0], sizeof(queue<unsigned>)*here.size());

So you are making a (shallow) copy of the internal representation of the queues, which includes some pointers. In the destructors of the queues, both the original and the copy try to free the same area of memory. This results in the double free.

The bottom line is: you can't just do a plain shallow memcpy of structures which store pointers and expect it to work.

reima
  • 2,076
  • 15
  • 22
0

You are copying queues as if they where contiguous in memory, and they aren't. Using fwrite, you must copy element by element, because as @reima said, at background you are using memcpy.

Best regards.

JP Cordova
  • 119
  • 9