Function not free-ing in time - c

I've had a look at a few other questions on SO but none of them seem to address a similar problem.
I have a function which sorts an array (using heap sort) and calculates the median. The heap sort routine has been taken directly from Numerical Recipies.
I am callocing and freeing an array inside the median function, but free doesn't seem to be freeing up the space in time. Here's some code to illustrate what I mean :
int calcMedian(int n1, int n2, int *dat)
{
int ii, npt;
int *inparr, retval;
npt = n2 - n1 + 1; /* Number of elements in array */
inparr = calloc(npt+1, sizeof(*inparr));
for(ii = n1; ii <= n2; ii++)
inparr[ii-n1+1] = dat[ii]; /* ii-n1+1 because heapsort function likes arrays to
start from 1 */
heapsortInt(npt, inparr); /* The error isn't here, function has been previously
debugged. Sorting is in-place.*/
if (npt % 2)
retval = inparr[(npt+1)/2];
else
retval = (inparr[npt/2]+inparr[npt/2+1])/2;
free(inparr);
return(retval);
}
The function heapsortInt has been quite thoroughly debugged and has been used in several other places without issue. Now I call my function calcMedian in a loop like so :
for(ii = 0; ii < maxval; ii++) {
index = ii * maxpt;
med1 = calcMedian(index, index+npt1[ii]-1, data1+index);
med2 = calcMedian(index, index+npt2[ii]-1, data2+index);
}
where the relevant variables are defined below :
int *data1, *data2;
int *npt1, *npt2;
data1 = calloc(maxval * maxpt, sizeof(*data1));
data2 = calloc(maxval * maxpt, sizeof(*data2));
npt1 = calloc(maxval, sizeof(*npt1));
npt2 = calloc(maxval, sizeof(*npt2));
So I'm basically passing different sections of one large array into calcMedian and getting back the necessary median values.
THE PROBLEM: calcMedian seems to be crashing when it hits the second function call. I ran it through valgrind, and this is what it told me:
Invalid read of size 4
at 0x43F67E: calcMedian /* Line no. pointing to calloc in calcMedian */
by 0x4416C9: main /* Line no pointing to second call of calcMedian */
Address 0x128ffdc0 is 6,128 bytes inside a block of size 110,788 free'd
at 0x4A063F0: free
by 0x43F728: calcMedian /* Line no. pointing to free in calcMedian */
by 0x4416C9: main /* Line no pointing to first call of calcMedian */
Is this a problem with free? Am I freeing and callocing too frequently? I don't know where to start debugging this. Any help will be wonderful!
DISCLAIMER: The computer with the actual code cannot access the internet. I've reproduced here as accurately as I can the code that causes the problem. If there are any missing semicolons etc. that's my fault, it definitely isn't there in the original code.
Edit: Fixed some transcription errors. I'll try and get the original code up ASAP, but from me looking through both of them now this seems to be fine.

The problem is the call to calcMedian.
You are adding index twice, once in the call, and then inside calcMedian.
It should be like this:
med1 = calcMedian(index, index+npt1[ii]-1, data1);
med2 = calcMedian(index, index+npt2[ii]-1, data2);

Related

How can I shorten an array?

I wanted to create a function that deletes from an array of segments the ones that are longer than a given number, by freeing the memory I don't need anymore. The problem is that the function I've created frees also all the memory allocated after the given point. How can I limit it, so that it frees just one pointer without compromising the others?
Here is the code I've written so far:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
typedef struct
{
double x1;
double y1;
double x2;
double y2;
} Segment;
double length(Segment* s)
{
return sqrt(pow(s->x1 - s->x2, 2) + pow(s->y1 - s->y2, 2));
}
// HERE IS THE PROBLEM!!
void delete_longer(Segment* as[], int n, double max_len)
{
for(int i = 0; i < n; i++)
{
if(length(as[i]) > max_len)
{
as[i] = NULL; // Those two lines should be swapped, but the problem remains
free(as[i]);
}
}
}
int main()
{
const int SIZE = 5;
Segment** arr = (Segment**)calloc(SIZE, sizeof(Segment*));
for(int i = 0; i < SIZE; i++)
{
arr[i] = (Segment*)malloc(sizeof(Segment));
}
srand(time(0));
for(int i = 0; i < SIZE; i++)
{
arr[i]->x1 = rand() % 100;
arr[i]->x2 = rand() % 100;
arr[i]->y1 = rand() % 100;
arr[i]->y2 = rand() % 100;
printf("Lungezza: %d\n", (int)length(arr[i]));
}
delete_longer(arr, SIZE, 80);
for(int i = 0; i < SIZE && arr[i]; i++)
{
printf("Lunghezza 2: %d\n", (int)length(arr[i]));
}
return 0;
}
First of all the free function should come after the instruction that sets the pointer to NULL, but that's not the main cause of the problem.
What causes the behaviour I described was the fact that the second for loop in the main stops after finding the first NULL pointer. Instead I should have written:
for(int i = 0; i < SIZE ; i++)
{
if(arr[i])
printf("Lunghezza 2: %d\n", (int)length(arr[i]));
}
You have two main problems:
In the delete function you write:
as[i] = NULL;
free(as[i]);
This is the wrong order. You must first free the memory and then set the element to null. But note that this is not the cause of your perceived problem, it only causes a memory leak (i.e. the memory of as[i] becomes inaccessible). You should write:
free(as[i]);
as[i] = NULL;
Your second problem is in your for loop, which now stops at the first null element. So not all the memory after it is deleted, you just don't print it. The loop should be for example:
for(int i = 0; i < SIZE; i++)
{
printf("Lunghezza 2: %d\n", arr[i]?(int)length(arr[i]):0);
}
Note: I agree with the discussion that free(NULL) may be implementation dependent in older implementations of the library function. In my personal opinion, never pass free a null pointer. I consider it bad practice.
There's no way to change the size of an array at runtime. The compiler assigns the memory statically, and even automatic arrays are fixed size (except if you use the last C standard, in which you can specify a different size at declaration time, but even in that case, the array size stands until the array gets out of scope). The reason is that, once allocated, the memory of an array gets surrounded of other declarations that, being fixed, make it difficult ot use the memory otherwise.
The other alternative is to allocate the array dynamically. You allocate a fixed number of cells, and store with the array, not only it's size, but also its capacity (the maximum amount of cell it is allow to grow) Think that erasing an element of an array requires moving all the elements behind to the front one place, and this is in general an expensive thing to do. If your array is filled with references to other objects, a common technique is to use NULL pointers on array cells that are unused, or to shift all the elements one place to the beginning.
Despite the technique you use, arrays are a very efficient way to access multiple objects of the same type, but they are difficult to shorten or enlengthen.
Finally, a common technique to handle arrays in a way you can consider them as variable length is to allocate a fixed amount of cells (initially) and if you need more memory to allocate double the space of the original (there are other approaches, like using a fibonacci sequence to grow the array) and use the size of the array and the actual capacity of it. Only in case your array is full, you call a function that will allocate a new array of larger size, adjust the capacity, copy the elements to the new copy, and deallocate the old array. This will work until you fill it again.
You don't post any code, so I shall do the same. If you have some issue with some precise code, don't hesitate to post it in your question, I'll try to provide you with a working solution.

realloc not allocating memory for next struct

I need to make an array of structs dynamically and I don't know the size when executing the malloc command. So I thought I could use realloc every time I need another struct! For example this code:
main:
int main(void) {
flights *flight_list = NULL;
int numFlights = 0;
numFlights = load_flights(&flight_list);
/* output flights. Problem: Only first flight is there, the second is not allocated! */
Here's the function:
short load_flights(flights **flight_list) {
flight_list[0] = calloc(1, sizeof(flights));
flight_list[0]->price = 69;
flight_list[0] = realloc(*flight_list, sizeof(flights)*2);
flight_list[1]->price = 70;
return 2; //num of flights-structs
The problem is, that actually 2 elements should be created, but only 1 element is there - check this debugging screenshot:
As you can see, flight_list[0] is there, but flight_list[1] not! But realloc should do the job?
Am I understanding anything wrong?
There's a bug in this line:
flight_list[1]->price = 70;
Both [] and -> dereference pointers. a[b] is equivalent to *(a+b) and a->b is equivalent to (*a).b. Your line therefore means:
(**(flight_list + 1)).price = 70;
However, flight_list (in load_flights) is a pointer to the flight_list variable in main! In the context of main, you're computing &flight_list + 1, which is an invalid pointer: You're getting the contents of memory that happens to be next to a local variable.
The correct code would be:
(*(*flight_list + 1)).price = 70;
*flight_list is the pointer returned by realloc. Here we can step one element ahead in the dynamic array.
We can also write this as:
(*flight_list)[1].price = 70;
Your flight_list is an array of pointers to pointers of flights.
With flight_list[0] = realloc(*flight_list, sizeof(flights)*2); you allocate space for two flights to the item flight_list[0], but flight_list itself remains unchanged. In fact, there is no code that allocates any space for flight_list at all, but maybe you just left out this code in your example.
If the realloc line of code is what you wanted, you should watch these memory locations in the debugger: flight_list[0][0] for the first flight, and flight_list[0][1] for the second.

c free pointer to structure

I'm writing in plain C and I have an issue about how to free a pointer to a structure.
I have a structure declared in the following way
typedef struct _RealMatrix {
uint nRows;
uint nCols;
real **matrix;
} RealMatrix;
Now, every time I need it I use the following code to allocate it
RealMatrix *realMatrixAlloc(uint n, uint m) {
loop_var(i);
RealMatrix *matrix;
matrix = malloc(sizeof(RealMatrix));
errcheck(matrix, "Unable to create real matrix structure.");
matrix->nRows = n;
matrix->nCols = m;
matrix->matrix = malloc(n*sizeof(real *));
matrix->matrix[0] = malloc(n*m*sizeof(real));
errcheck(matrix->matrix && matrix->matrix[0], "Unable to get requested memory for real matrix of dimensions: (%u, %u).", n, m);
f_i(i < n) matrix->matrix[i] = matrix->matrix[0] + i*m;
return matrix;
}
where errcheck() is a allocation checking macro. Everything works just fine until I try to deallocate it calling
freeRealMatrix(&myRealMatrix);
which will
free((*ma)->matrix[0]),
free((*ma)->matrix)
free(*ma).
*ma = NULL;
with suitable checks to avoid following any NULL pointer. Here "ma" is the pointer TO THE POINTER to the structure: the function declaration reads
void freeRealMatrix(RealMatrix **ma);
However when this function returns I find out that "myRealMatrix" is still addressing an existing structure, which was not deallocated as I expected by free(*ma). On the other hand the array (*ma)->matrix has been successfully deallocated.
Any ideas about what am I doing wrong? This is driving me crazy...
Thanks in advance!
UPDATE:
I copied the code and executed in a brand new program... It works precisely as expected. I noticed that the address contained in "myRealMatrix" isn't the same as the address pointed by *ma. Well... Sort of: it seems truncated! Instead of being 0x106a50 it is just 0x106a and no more. The last two hex digits are missing every time!
After a free, your pointer continues to contain the address of the freed location. You can not continue addressing this location though. It can be used for something else.
You may want to explicitly set it to NULL after the third free statement:
*ma = NULL;

free() invalid pointer - freeing array of pointers fails

I have been debugging a piece of legacy code, running on an XScale (arm v5te) System with linux, that crashes reproducible.
I have debugged using gdb and set MALLOC_CHECK_ to 1. It's a lot of code, so just some snippets:
We have this structure:
typedef struct {
...clipped..
char **data_column_list;
/** data column count */
int data_column_cnt;
...clipped
} csv_t;
We initialize the columns in a function, putting them in a variable "columns"
/* Allocating memory for pointer to every register id */
columns = (char **) malloc(column_cnt * sizeof(char *));
column_cnt = 0;
/* loop over all sensors */
for(i=0; i<cfg.sen_cnt; i++) {
/* loop over all registers */
for(j=0; j<cfg.sen_list[i]->data_cnt; j++) {
/* Storing all the pointers to id */
columns[column_cnt++] = cfg.sen_list[i]->data_list[j]->id;
}
}
In another function, what happens is this:
/* free the previous list */
csv_free(lc_csv);
lc_csv->data_column_list = columns;
lc_csv->data_column_cnt = column_cnt;
csv_free being:
void csv_free(csv_t *csv) {
if(csv->data_column_cnt > 0)
free(csv->data_column_list);
csv->data_column_cnt = 0;
}
Now, there is another function, building the whole "cfg"/config structure, that contains these ids.
Code frome above: cfg.sen_list[i]->data_list[j]->id; where cfg is a struct, sen_list is an array of pointers to structs, data_list is an array of pointers to other structs, that contain a string "id".
Whe the program gets a signal SIGUSR1, the config is being updated. All of these data_list and sen_list structs are being freed, then new ones are generated.
Then with the first function, new collumns of ids are generated and put into the csv structure, but the old list is being freed before.
Thats where it crashes. In csv_free.
*** glibc detected *** /root/elv: free(): invalid pointer: 0x0001ae88 ***
I thought it should be like this. You have an array of pointers. When you free the pointers, you have to free the pointer, pointing to a set of pointers (the array).
Or put in code terms, the above situation should be analog to:
char **ar = malloc(n * sizeof(char *));
char *xn = malloc(10 * sizeof(char)); // Do for 0 to n strings
...
ar[n] = xn; // Do for 0 to n strings
...do stuff...
free(xn); // Do for 0 to n strings
free(ar);
When the structs, containing the id strings, are freed, I still have my pointer arrays with (invalid) pointers, not null pointers:
(gdb) p csv
$40 = {sysid = 222, ip = '\0' <repeats 49 times>,
module = "elv_v2", '\0' <repeats 14 times>, format_type = 1, msg_id = 0,
data_column_list = 0x1ae88, data_column_cnt = 10, pub_int = 30,
line_cnt = 0, pub_seq = -1, format = 0x18260}
(gdb) p csv.data_column_list[0]
$41 = 0x1b378 "0"
But I get the above error message (or SIGABRT without the MALLOC_CHECK_).
I don't understand this at all. I have to free this array of pointers, or it will become a memory leak. There is no other call of free before that, that I could find. I don't know why csv.data_column_list is considered an invalid pointer.
Valgrind is unfortunately not availiable on arm v5te :(
Have been debugging this for hours and hours and would be happy for any help.
Thank you very much,
Cheers,
Ben
UPDATE:
I'm wondering if it could be connected to some "scope" issue. There is almost identical code in another application, which works. The function which crashes, "csv_free" is used by both programs (statically linked). The only difference is, that the struct containing the pointer to be freed is declared and defined normally in the working program and declared as external and defined in another file than main.c
Calling "free" manually in main.c works, while calling "csv_free" crashes. Riddle me this...
9 out of 10 times when I run into free() errors the problem actually started in the allocation or initialization, so let's verify that a bit:
Where do you actually assign columns to csv.data_columns_list before you call csv_free? If it's uninitialized when you free(), that would explain the error.
In the second code block, if the initial column_cnt (which I guess is set
elsewhere?) is less than the column_cnt after the loop you would be writing outside the
array. One would hope MALLOC_CHECK_ would catch that, but what happens if you assert as
follows:
/* Allocating memory for pointer to every register id */
columns = (char **) malloc(column_cnt * sizeof(char *));
int old_column_cnt = column_cnt;
column_cnt = 0;
/* loop over all sensors */
for(i=0; i<cfg.sen_cnt; i++) {
/* loop over all registers */
for(j=0; j<cfg.sen_list[i]->data_cnt; j++) {
/* Storing all the pointers to id */
columns[column_cnt++] = cfg.sen_list[i]->data_list[j]->id;
}
}
assert(old_column_cnt >= column_cnt);
Looking over my old questions I saw this. I can't really verify, since I don't work at that company anymore, but thinking of other issues we had, I think wildplasser was right.
Calling any large functions from within signal handlers is a bad idea. Especially if you haven't check whether everything you do is reentrant. It was legacy code, so at least it's not completely my fault ;)
Nowadays I would set a flag in the signal handler and call the routine in my main loop, when that flag is set (or something like that).

Using malloc and free in C/C++ and getting error HEAP CORRUPTION DETECTED

I am having a problem when free(position) is run.
void printTree(nodeT node, int hieght)
{
int *position;
position = (int*)malloc(hieght * sizeof(int*));
for (int i = 0; i <= hieght; i++)
{
position[i] = 0;
}
BOOLEAN DONE = FALSE;
while (DONE == FALSE)
{
printMoveDown(&node, position);
printLEAFNode(&node, position);
DONE = printMoveUp(&node, position);
printSingleKey(&node, position);
}
free(position);
position = NULL;
}
The full error message I get from VS2010 is HEAP CORRUPTION DETECTED: after normal block (#64) at 0x00031390. CRT detected that the application wrote to memory after end of heap.
The debugger says the problem occurs while at in: dbgheap.c
extern "C" void __cdecl _free_dbg_nolock
line 1376: if (!CheckBytes(pbData(pHead) + pHead->nDataSize, _bNoMansLandFill, nNoMansLandSize))
if (pHead->szFileName) {..}
else { this is where the program stops }
I tried setting up the same situation with less stuff going on to see if I could narrow the problem down.
void function (int y)
{
int *x;
x = (int*)malloc(y * sizeof(int*));
free(x);
x = NULL;
}
This is the same thing as above without the for loop and while loop. This works. Removing the for loop is what made it work. I don't know why. I looked up what the CRT was but it was all pretty new concepts to me and I assume that I can solve this problem without knowing about these CRTs.
The for loop assigns values to the memory allocated for position, beyond that I can't think of why this causes a problem.... actually now that I think about it. I changed the loop to be height + 1 which fixed the problem.
It should be:
position = malloc(hieght * sizeof(int));
or:
position = malloc(hieght * sizeof *position);
It's undefined behavior the way you have it. You're probably just getting lucky because int and int* are the same size.
And the typical correct way to write the loop is:
for (int i = 0; i < hieght; i++)
{
position[i] = 0;
}
You can also use calloc here:
position = calloc(hieght, sizeof *position);
and the memory will be zeroed for you, so you don't have to loop.
Also, if this is really C, the cast is superfluous.
I think the problem in the loop is the <= which really should be <.
Consequently the loop goes round one time too many and corrupts the next item on the heap!

Resources