Reputation: 911
Im trying to create an exact copy of a text file, and I am using a circular buffer.
The write method I am using is:
void addItem(CircularBuffer *cBuff, BufferItem *cbItem) {
cBuff->cBuffItems[cBuff->lastInd] = *cbItem;
cBuff->lastInd = ( ((cBuff->lastInd) + 1) % cBuff->size);
if (cBuff->lastInd == cBuff->startInd)
{
cBuff->startInd = (cBuff->startInd + 1) % cBuff->size; // Overwriting full buffer.
}
}
And here is how I am copying each char into the buffer:
BufferItem result;
char ch;
while( ( ch = fgetc(fp) ) != EOF ){
result.offset = ftell(fp);
result.data = ch;
addItem(&cBuff, &result);
}
It only writes the first three characters then gives me a segmentation fault. I made sure the buffer size is big enough, ive tried different datasets, all give the same result (only the first 3 chars copied into buffer).
If I dont add it to the buffer, and just print result.offset, and result.data I get what I expect. So addItem must be the problem, If I delete the second line in addItem, it works but obviously it just overwrites the first spot.
What am I doing wrong?
Here is the circular buffer and circular buffer implementation:
// Circular buffer items.
typedef struct {
char data ;
off_t offset ;
} BufferItem ;
// Circular buffer
typedef struct {
int startInd; // Index of first element added to buffer.
int lastInd; // Index of most recent element added to buffer.
int size; // Number of elements in circular buffer.
BufferItem *cBuffItems; // Circular buffer items.
} CircularBuffer;
void initializeBuffer(CircularBuffer *cBuff, int size) {
cBuff->cBuffItems = calloc(cBuff->size, sizeof(BufferItem));
cBuff->size = size + 1;
cBuff->startInd = 0;
cBuff->lastInd = 0;
}
And like I mentioned, I did initialize the buffer, here is a simplified version of main:
int main( int argc, char *argv[] )
{
if (argc != 4)
{
printf("Expected 3 arguments, received %d\n", argc - 1);
return 1;
}
int bufSize; // Capacity of BufferItems in circular buffer.
char *file; // Pathname of file to be copied.
char *copy; // Name to be given to the copy.
sscanf(argv[1], "%d", &bufSize);
file = argv[2];
copy = argv[3];
initializeBuffer(&cBuff, bufSize);
// Open file to be copied.
FILE *fp = fopen(file, "r" );
// Create copy file.
FILE *cp = fopen(copy, "w+" ); // Overwrite if file exists.
BufferItem result;
char ch;
while( ( ch = fgetc(fp) ) != EOF ){
result.offset = ftell(fp);
result.data = ch;
addItem(&cBuff, &result);
}
fclose(fp);
fclose(cp);
return 0;
}// Main.
Upvotes: 0
Views: 1223
Reputation: 754570
Once the initialize code is shown, the problem is clear: you are using cBuff->size
before you set it.
void initializeBuffer(CircularBuffer *cBuff, int size) {
cBuff->cBuffItems = calloc(cBuff->size, sizeof(BufferItem));
cBuff->size = size + 1;
cBuff->startInd = 0;
cBuff->lastInd = 0;
}
Consequently, you're using a quasi-random size, and getting correspondingly quasi-random results. As you can now see, it is the code you didn't show originally that is causing the trouble — that's why we have to demand to see a workable example!
You can fix it pretty trivially:
void initializeBuffer(CircularBuffer *cBuff, int size) {
cBuff->cBuffItems = calloc(size + 1, sizeof(BufferItem));
cBuff->size = size + 1;
cBuff->startInd = 0;
cBuff->lastInd = 0;
}
This uses the parameter size
instead of the uninitialized element of cBuff
. I suggest that allocating one number of items and then saying that there is a different number of them available for use is going to cause trouble. I've opted to add one to both numbers; on the whole, though, it might be better to use the value of size
without the increment.
You could also reorder the assignments (so you set cBuff->size
before you allocate cBuff->cBuffItems
); that would also work (as long as you make the allocation size consistent with the recorded size.
You should, arguably, check the result of calloc()
.
Upvotes: 1