c free pointer to structure - c

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;

Related

seg fault from 2d array allocation

i have a struct "cell" defined as
typedef struct{
int id;
terrainType terrain;
} cell;
i then make a 2d array of cells with
cell** makeCellGrid(int sizeX, int sizeY)
{
cell** theArray;
int i;
theArray = (cell**) malloc(sizeX*sizeof(cell*));
for ( i = 0; i < sizeX; i++)
{
theArray[i] = (cell*) malloc(sizeY*sizeof(cell));
}
return theArray;
}
at first i thought this was working fine but a few seg faults later i discovered that with some values (e.g. makeCellGrid(32, 87) ) it breaks.
im fairly fresh with C pointers and memory junk and was hoping some one could point me in the right direction here.
with lower number bounds i had no issue accessing it with
map[i][j].id = x;
and so on
EDIT: forgot to add, from testing, the seg fault originate from
theArray[i] = (cell*) malloc(sizeY*sizeof(cell));
The code lacks error checking for the malloc() system call.
So if the first call to malloc() failed the second one (in the loop) tries to assign memory to NULL which indeed leads to the segmentation violation your are witnessing.
You might consider modifing you code like so:
#include <stdlib.h>
typedef struct {
int id;
TerrainType terrain;
} CellType;
void freeCellGrid(CellType ** ppCells, size_t sizeX)
{
size_t i = 0;
for (; i < sizeX; ++i)
{
free(ppCells[i]);
}
free(ppCells);
}
CellType ** makeCellGrid(size_t sizeX, size_t sizeY)
{
CellType ** ppCells = malloc(sizeX * sizeof(*ppCells));
if (ppCells)
{
size_t i = 0;
for (; i < sizeX; ++i)
{
ppCells[i] = malloc(sizeY * sizeof(**ppCells));
if (NULL == ppCells[i])
{
freeCellGrid(ppCells, i);
ppCells = NULL;
break;
}
}
}
return ppCells;
}
Notes on my modifications:
Always check system calls for errors (in the case of malloc() on error NULL is returned)
Better use an unsigned type to access memory/array indicies; size_t is meant for this
In C there is no need to cast the value returned by a void * function like malloc()
Always try to initialise variables as soon as possible; un-initilaised variables very easily lead to "irrational" behaviour of the application
If working with pointers, it might be helpfull to 'code' the level of indirection into their names (I did this here by using the prefix pp to indicated that it's a 2-level indirection)
types are different from variables: One way to distinguish this is by starting type names using capitals (CellType) and variables using small letters (ppCells).
If allocating memory to a pointer and it matters that the size of the allocated memory some suits the pointer's type it's always more secure to use the (dereferenced) pointer itself as argument to the sizeof operator then some type. As the declaration of the pointer the memory is allocated to might be changed during develpment and the adjustment of the argument to malloc() will be forgotten. To cut it short: doing as I did is less error prone.
If encapsulating the dynamical creation of structures (including arrays) it is a could idea to also implement a method which de-allocates it (here: freeCellGrid()). Even better start of with coding this deallocator first, as then you have it by hand when coding the allocator's error handling (as shown for the second call to malloc()).

Double pointer memory allocation to a struct in C

Can't find what is wrong with this code, it works as expected when inputting exactly 4 values, but on the fifth call (before it even asks for scanf) it always gives me this error:
* glibc detected ./a2: double free or corruption (fasttop): 0x0916e018 **
Here's some code of my program:
typedef struct {
int i;
char str[25];
} typeX;
int main(){
int dSize = 0;
int *dSizePtr = &dSize;
dPointer = (typeX **)malloc(sizeof(typeX *)); // makes an array of pointers
int i;
for (i = 0; i < 100; i++)
makeElement(dPointer, dSizePtr); // Puts values into those pointers
free(dPointer);
return 0;
}
void makeElement(dPointer **, int *dSizePtr){
dPointer = (typeX **)realloc(dPointer, sizeof(typeX *)*(*dSizePtr+1)); // grow the array by one
if (typeX == NULL)
return; // some kind of quit statement, just return for now
dPointer[*dSizePtr] = (typeX *)malloc(sizeof(typeX)); // make a new pointer in the array
scanf("%s", dPointer[*dSizePtr]->str); // input the values of the struct (have to use scanf)
char input[20];
scanf("%s", input);
dPointer[*dSizePtr]->int = atoi(input);
++(*dSizePtr);
}
I know I don't have to make a dSizePtr and I can just pass in &dSize, but the way my program is currently set up (this isn't exactly the same, just compressed for readability), that's the way I have to pass it.
I honestly have no idea why this error is coming up. Been looking at my code for hours and reading online and haven't found a solution. Any help will be greatly appreciated!
The problem is that your function makeElement get the value of dPointer, not its reference. When you realloc the data, the originally allocated chunk is freed. But the dPointer outside of the makeElement scope is not changed;
The runtime error is delayed as the actual memory allocation is performed in quantities bigger than sizeof(typeX*)
This line is causing the double free.
dPointer = (typeX **)realloc(dPointer, sizeof(typeX *)*(*dSizePtr+1)); // grow the array by one
For the first few iterations of the loop in the caller the block of memory is large enough that realloc() doesn't have to do anything, and thus it returns the same pointer passed to it. But at some point the block of memory is too small and realloc() has to allocate a new block of memory and returns a pointer to it. That returned pointer is assigned to dPointer in makeElement() but it does not change the value of dPointer in the caller. So the caller continues to pass the old dPointer value into makeElement(), which passes it to realloc(), which notices that this pointer has been freed (by the call to realloc() that expanded the size of the array).

pointer and which is pointed by the pointer

Update : Sorry, just a big mistake. It is meaningless to write int *a = 3; But please just think the analogy to the case like TCHAR *a = TEXT("text"); (I edited my question, so some answers and comments are strange, since they are for my original question which is not suitable)
In main function, suppose I have a pointer TCHAR *a = TEXT("text"); Then it excutes the following code:
int i;
for (i = 0; i < 1000; i++) {
a = test(i);
}
with the function TCHAR* test(int par) defined by:
TCHAR* test(int par)
{
TCHAR *b = TEXT("aaa");
return b;
}
My question is, after executing the above code, but before the program ends, in the memory:
1. the pointer `a` remains?
2. The 1000 pointers `b` are deleted each time the function test(...) exits ?
3. But there are still 1000 memory blocks there?
In fact, my question is motivated from the following code, which shows a tooltip when mouse is over a tab item in a tab control with the style TCS_TOOLTIPS:
case WM_NOTIFY
if (lpnmhdr->code == TTN_GETDISPINFO) {
LPNMTTDISPINFO lpnmtdi;
lpnmtdi = (LPNMTTDISPINFO)lParam;
int tabIndex = (int) wParam; // wParam is the index of the tab item.
lpnmtdi->lpszText = SetTabToolTipText(panel->gWin.At(tabIndex));
break;
}
I am thinking if the memory usage increases each time it calls
SetTabToolTipText(panel->gWin.At(tabIndex)), which manipulates with TCHAR and TCHAR* and return a value of type LPTSTR.
Yes, the pointer a remains till we return from the main function
The variable b (a 4-byte pointer) is automatic. It is created each time we call test function. Once we return from it, the variable disappears (the pointer). Please note, the value to which b points isn't affected.
No. In most of the cases, I think, there will be only one block allocated during compilation time (most likely in the read-only memory) and the function will be returning the same pointer on every invocation.
If SetTabToolTipText allocates a string inside using some memory management facilities new/malloc or some os-specific, you should do an additional cleanup. Otherwise there'll be a memory leak.
If nothing like this happens inside (it's not mentioned in the documentation or comments etc), it's most likely returning the pointer to some internal buffer which you typically use as readonly. In this case, there should be no concerns about a memory consumption increase.
You dont allocate any memory so you don't have to worry about memory being freed. When your vaiables go out of scope they will be freed automatically. In this function
int test(int par)
{
int *b = par;
}
you don't have a return value even though the function says that is will return an int, so you should probably do so as in this line
for (i = 0; i < 1000; i++) {
a = test(i);
}
you assign to a the value that is returned by test(). Also
int* a = 3;
int* b = par;
are asking for trouble. You are assigning integer values to a pointer variable. You should probably rethink your above code.
Pointer should contain adress... so int* a = 3 is something meaningless... And in function you don't allocate memory for int (only for par variable, which then destroy when the function ends), you allocate memory for storing adress in int* b, this memory also free when the funciton ends.

C using malloc and duplicating array

I am supposed to follow the following criteria:
Implement function answer4 (pointer parameter and n):
Prepare an array of student_record using malloc() of n items.
Duplicate the student record from the parameter to the array n
times.
Return the array.
And I came with the code below, but it's obviously not correct. What's the correct way to implement this?
student_record *answer4(student_record* p, unsigned int n)
{
int i;
student_record* q = malloc(sizeof(student_record)*n);
for(i = 0; i < n ; i++){
q[i] = p[i];
}
free(q);
return q;
};
p = malloc(sizeof(student_record)*n);
This is problematic: you're overwriting the p input argument, so you can't reference the data you were handed after that line.
Which means that your inner loop reads initialized data.
This:
return a;
is problematic too - it would return a pointer to a local variable, and that's not good - that pointer becomes invalid as soon as the function returns.
What you need is something like:
student_record* ret = malloc(...);
for (int i=...) {
// copy p[i] to ret[i]
}
return ret;
1) You reassigned p, the array you were suppose to copy, by calling malloc().
2) You can't return the address of a local stack variable (a). Change a to a pointer, malloc it to the size of p, and copy p into. Malloc'd memory is heap memory, and so you can return such an address.
a[] is a local automatic array. Once you return from the function, it is erased from memory, so the calling function can't use the array you returned.
What you probably wanted to do is to malloc a new array (ie, not p), into which you should assign the duplicates and return its values w/o freeing the malloced memory.
Try to use better names, it might help in avoiding the obvious mix-up errors you have in your code.
For instance, start the function with:
student_record * answer4(const student_record *template, size_t n)
{
...
}
It also makes the code clearer. Note that I added const to make it clearer that the first argument is input-only, and made the type of the second one size_t which is good when dealing with "counts" and sizes of things.
The code in this question is evolving quite quickly but at the time of this answer it contains these two lines:
free(q);
return q;
This is guaranteed to be wrong - after the call to free its argument points to invalid memory and anything could happen subsequently upon using the value of q. i.e. you're returning an invalid pointer. Since you're returning q, don't free it yet! It becomes a "caller-owned" variable and it becomes the caller's responsibility to free it.
student_record* answer4(student_record* p, unsigned int n)
{
uint8_t *data, *pos;
size_t size = sizeof(student_record);
data = malloc(size*n);
pos = data;
for(unsigned int i = 0; i < n ; i++, pos=&pos[size])
memcpy(pos,p,size);
return (student_record *)data;
};
You may do like this.
This compiles and, I think, does what you want:
student_record *answer4(const student_record *const p, const unsigned int n)
{
unsigned int i;
student_record *const a = malloc(sizeof(student_record)*n);
for(i = 0; i < n; ++i)
{
a[i] = p[i];
}
return a;
};
Several points:
The existing array is identified as p. You want to copy from it. You probably do not want to free it (to free it is probably the caller's job).
The new array is a. You want to copy to it. The function cannot free it, because the caller will need it. Therefore, the caller must take the responsibility to free it, once the caller has done with it.
The array has n elements, indexed 0 through n-1. The usual way to express the upper bound on the index thus is i < n.
The consts I have added are not required, but well-written code will probably include them.
Altought, there are previous GOOD answers to this question, I couldn't avoid added my own. Since I got pascal programming in Collegue, I am used to do this, in C related programming languages:
void* AnyFunction(int AnyParameter)
{
void* Result = NULL;
DoSomethingWith(Result);
return Result;
}
This, helps me to easy debug, and avoid bugs like the one mention by #ysap, related to pointers.
Something important to remember, is that the question mention to return a SINGLE pointer, this a common caveat, because a pointer, can be used to address a single item, or a consecutive array !!!
This question suggests to use an array as A CONCEPT, with pointers, NOT USING ARRAY SYNTAX.
// returns a single pointer to an array:
student_record* answer4(student_record* student, unsigned int n)
{
// empty result variable for this function:
student_record* Result = NULL;
// the result will allocate a conceptual array, even if it is a single pointer:
student_record* Result = malloc(sizeof(student_record)*n);
// a copy of the destination result, will move for each item
student_record* dest = Result;
int i;
for(i = 0; i < n ; i++){
// copy contents, not address:
*dest = *student;
// move to next item of "Result"
dest++;
}
// the data referenced by "Result", was changed using "dest"
return Result;
} // student_record* answer4(...)
Check that, there is not subscript operator here, because of addressing with pointers.
Please, don't start a pascal v.s. c flame war, this is just a suggestion.

Basic question: C function to return pointer to malloc'ed struct

About C structs and pointers...
Yesterday I wrote sort of the following code (try to memorize parts of it out of my memory):
typedef struct {
unsigned short int iFrames;
unsigned short int* iTime; // array with elements [0..x] holding the timing for each frame
} Tile;
Tile* loadTile(char* sFile)
{
// expecting to declare enough space for one complete Tile structure, of which the base memory address is stored in the tmpResult pointer
Tile* tmpResult = malloc(sizeof(Tile));
// do things that set values to the Tile entity
// ...
// return the pointer for further use
return tmpResult;
}
void main()
{
// define a tile pointer and set its value to the returned pointer (this should also be allowed in one row)
// Expected to receive the VALUE of the pointer - i.e. the base memory address at where malloc made space available
Tile* tmpTile;
tmpTile = loadTile("tile1.dat");
// get/set elements of the tile
// ...
// free the tile
free(tmpTile);
}
What I see: I cán use the malloced Tile structure inside the function, but once I try to access it in Main, I get an error from Visual Studio about the heap (which tells me that something is freed after the call is returned).
If I change it so that I malloc space in Main, and pass the pointer to this space to the loadTile function as an argument (so that the function does no longer return anything) then it does work but I am confident that I should also be able do let the loadTile function malloc the space and return a pointer to that space right?!
Thanks!!
There's nothing wrong with what you're trying to do, or at least not from the code here. However, I'm concerned about this line:
unsigned short int* iTime; // array with elements [0..x] holding the timing for each frame
That isn't true unless you're also mallocing iTime somewhere:
Tile* tmpResult = malloc(sizeof(Tile));
tmpResult->iTime = malloc(sizeof(short) * n);
You will need to free it when you clean up:
free(tmpTile->iTime);
free(tmpTile);
You are probably writing over memory you don't own. I guess that in this section:
// do things that set values to the Tile entity
you're doing this:
tmpResult->iFrames = n;
for (i = 0 ; i < n ; ++n)
{
tmpResult->iTime [i] = <some value>;
}
which is wrong, you need to allocate separate memory for the array:
tmpResult->iTime = malloc (sizeof (short int) * n);
before writing to it. This make freeing the object more complex:
free (tile->iTime);
free (tile);
Alternatively, do this:
typedef struct {
unsigned short int iFrames;
unsigned short int iTime [1]; // array with elements [0..x] holding the timing for each frame
} Tile;
and malloc like this:
tile = malloc (sizeof (Tile) + sizeof (short int) * (n - 1)); // -1 since Tile already has one int defined.
and the for loop remains the same:
for (i = 0 ; i < n ; ++n)
{
tmpResult->iTime [i] = <some value>;
}
but freeing the tile is then just:
free (tile);
as you've only allocated one chunk of memory, not two. This works because C (and C++) does not do range checking on arrays.
You code, with as little changes as I could live with, works for me:
#include <stdio.h>
#include <stdlib.h>
typedef struct {
unsigned short int iFrames;
unsigned short int* iTime;
} Tile;
Tile *loadTile(char* sFile) {
Tile *tmpResult = malloc(sizeof *tmpResult);
if (!tmpResult) return NULL;
/* do things that set values to the Tile entity */
/* note that iTime is uninitialized */
tmpResult->iFrames = 42;
(void)sFile; /* used parameter */
return tmpResult;
}
int main(void) {
Tile* tmpTile;
tmpTile = loadTile("tile1.dat");
if (!tmpTile) return 1;
printf("value: %d\n", tmpTile->iFrames);
free(tmpTile);
return 0;
}
The code you showed looks OK, the error must be in the elided code.
Whatever problem you are having, it is not in the code shown in this question. Make sure you are not clobbering the pointer before returning it.
This should work fine... could just be a warning from VisualStudio that you are freeing a pointer in a different function than it was malloced in.
Technically, your code will work on a C compiler. However, allocating dynamically inside functions and returning pointers to the allocated data is an excellent way of creating memory leaks - therefore it is very bad programming practice. A better way is to allocate the memory in the caller (main in this case). The code unit allocating the memory should be the same one that frees it.
Btw if this is a Windows program, main() must be declared to return int, or the code will not compile on a C compiler.

Resources