On to the next memory bug. Truly amazing how many of these were hiding behind wonky input.
Here is my free_events() function, which takes the head of the linked list and frees the entire list.
Code:
void free_events(event *current)
{
while (current->next)
{
current = current->next;
free(current->prev->signal);
free(current->prev->filtered_signal);
free(current->prev->filtered_level_histogram);
free(current->prev->level_histogram);
free(current->prev->peaks);
free(current->prev);
}
free(current->signal);
free(current->filtered_signal);
free(current->filtered_level_histogram);
free(current->level_histogram);
free(current->peaks);
free(current);
}
here is the event struct itself:
Code:
struct Event
{
int index;
long long int start;
long long int finish;
long int length;
int type;
double area;
double open_current;
double *signal;
double *filtered_signal;
long int *level_histogram;
long int *filtered_level_histogram;
double *peaks;
int numpeaks;
double binsize;
long int padding;
struct Event *next;
struct Event *prev;
};
typedef struct Event event;
At the end of my program I free the linked list of events. And when I do, it hangs on the call free(current->filtered_level_histogram). I don't think this is important in an of itself, it's just the indication that there are memory issues. I have verified that the memory is allocated properly, so it's getting trashed somewhere in the middle. Indeed, at this point the program is done and the output is correct, so as far as I can tell it doesn't harm anything (yet). But it means there are still pointer issues which could bite me later, so I need to find it.
Turns out that the problem boils down to a single line. If I comment it out (and make some minor changes elsewhere so that its intended result isn't missed) the problem disappears. The line is below:
Code:
void generate_trace(FILE *input, event *current, double *dcof, int *ccof, double scale, int order)
{
long int padding;
long long int position;
long int read;
double *tempfiltered;
padding = order+1;
current->padding = padding;
position = current->start - padding;
if ((current->signal = calloc(current->length + 2*padding,sizeof(double)))==NULL)
{
printf("Cannot allocate trace array\n");
return;
}
if ((current->filtered_signal = calloc(current->length + 2*padding,sizeof(double)))==NULL)
{
printf("Cannot allocate filtered trace array\n");
return;
}
if ((tempfiltered = calloc(current->length + 2*padding,sizeof(double)))==NULL)
{
printf("Cannot allocate temporary filtered trace array\n");
return;
}
if (fseeko64(input,position*2*sizeof(double),SEEK_SET))
{
printf("Cannot location file position at sample %lld\n",position);
return;
}
read = read_current(input, current->signal, position, current->length + 2*padding);
if (read != current->length + 2*padding)
{
printf("Unable to read %ld samples for event %d: obtained %ld\n",current->length + 2*padding,current->index,read);
}
printf("filtering\n");
filter_signal(current->signal, tempfiltered, current->filtered_signal, dcof, ccof, scale, order, read);
printf("done filtering\n");
free(tempfiltered);
}
Finally, the read_current() function is here, whicih reads from a binary file and swaps the endianness. Note that this function is used elsewhere in the code, without issue. So something about that particular line is causing what I am guessing is going out of bounds on an array.
Code:
long int read_current(FILE *input, double *current, long long int position, long int length)
{
union{
double d;
unsigned long long int i;
}ud;
long int i;
long int read = 0;
if (fseeko64(input,position*2*sizeof(double),SEEK_SET))
{
return 0; //error checking
}//move to the relevent position in the file
for (i = 0; i < length; i++)
{
read += fscanf(input,"%8c%*8c",(char *)&ud.d);
swapByteOrder(&ud.i);
current[i] = ud.d;
}
return read;
}
Again, the output is correct, as far as I can tell. But some memory is getting trashed somewhere. Any ideas?