How can I free a struct pointer that i need - c

I am trying to avoid memory leaks in my code. I need to de-allocate pElement, line and pSecond, without losing the values inside pImage. Because I need to print those values inside my print function.
My add function contains struct GraphicElement *pElements;, struct GraphicElement *pSecond;, struct Point point;.
I allocate memory using malloc for each struct and then add the values and then I pass the final values into pImage. All my other functions work perfectly besides the fact that I always end up with 3 memory leaks. Because I didnt not free(pSecond);....free(pElement)...free(line);
If I try to free them before my function exits and after passing the values into pImage. My values all get erased.
How can I free those values inside my add function locally?
struct Point
{
int x, y;
};
struct Line
{
Point start;
Point end;
};
struct GraphicElement
{
enum{ SIZE = 256 };
unsigned int numLines; //number of lines
Line* pLines; //plines points to start and end
char name[SIZE];
};
typedef struct
{
unsigned int numGraphicElements;
GraphicElement* pElements; //the head points to pLines
} VectorGraphic;
void InitVectorGraphic(VectorGraphic*); //initializes pImage->pElement
void AddGraphicElement(VectorGraphic*); //Used to add
void ReportVectorGraphic(VectorGraphic*); // prints pImage contents
void CleanUpVectorGraphic(VectorGraphic*); //deallocates memory

How can I free those values inside my add function locally?
It is not possible to explicitly free a memory allocated locally. Nor to locally free some memory. Once freed, a memory slot cannot be accessed and the data stored inside are lost.
In C, you have two option to allocate some memory: you can allocate it on the heap or on the stack. The memory slots reserved on the heap can be accessed globally and will remain until they are explicitly freed. The one reserved on the stack are only valid while you stay within the context they were created.
Let's say you execute the following code :
void func()
{
int x = 3; // [2]
int * p = & x; // [3]
}
int main()
{
func(); // [1]
// [4]
return 0;
}
The instruction [2] will allocate some memory on the stack. The second one ([3]) will do the same and will store the address of the of the first variable in the new memory slot. After the function returns ([4]), this memory is freed. Graphically, here is what happens :
Context STACK Address
+---------+
| | 0xa1
main | | 0xa0
+---------+
[1] +---------+
=====> | |
func | | 0xa2
+---------+
| | 0xa1
main | | 0xa0
+---------+
[2] +---------+
=====> | |
func | 3 | 0xa2 <-- x
+---------+
| | 0xa1
main | | 0xa0
+---------+
[3] +---------+
=====> | 0xa2 | 0xa3 <-- p
func | 3 | 0xa2 <-- x
+---------+
| | 0xa1
main | | 0xa0
+---------+
[4] +---------+
=====> | | 0xa1
main | | 0xa0
+---------+
So if i use malloc inside a function. Once I exist the function the allocated memory on the heap is freed automatically?
It's the opposite. If you use, a function like malloc, the memory slot will be allocated on the heap. So if we change the line [3] above to something like
int * p = malloc(sizeof(int)); // [3]
The memory allocated on the stack will be freed as you'll leave the function, but the memory allocated on the heap will remain allocated and will still be accessible, until you free it. Graphically :
HEAP Address Free (y/n)
+---------+
| | 0xb4 - Yes
| | 0xb3 - Yes
+---------+
Context STACK Address
[3] +---------+ +---------+
=====> | 0xb4 | 0xa3 <-- p | | 0xb4 - No
func | 3 | 0xa2 <-- x | | 0xb3 - Yes
+---------+ +---------+
| | 0xa1
main | | 0xa0
+---------+
[4] +---------+ +---------+
=====> | | 0xa1 | | 0xb4 - No !!! Leak !!!
main | | 0xa0 | | 0xb3 - Yes
+---------+ +---------+
As you can see, after you leave the function, you have a memory leak as you don't have any pointer to the dynamically allocated memory. One way to avoid this is to return the pointer (so to pass the address of the new memory slot to the calling function) or to store it somewhere to free it later. It's also possible to allocate the memory before calling the function and to pass it to the function as a parameter. It really depends on your application.

Related

Program crash on memset?

I am struggling with memset.
If I write in my array my program crashes. If I comment out the memset i have no problems.
My type struct:
typedef struct
{
char Frage [maxLEN_F_A];
char Antwort[maxLEN_F_A];
} Fragenfeld;
My declaration of the struct:
Fragenfeld QuizFragen[maxFragen];
Fragenfeld *ptrQuizFragen = QuizFragen;
The memset call:
memset(&ptrQuizFragen,0,maxFragen*sizeof(Fragenfeld));
My function, where I edit the value of the adress:
int Fragen_einlesen(Fragenfeld *Quizfragen)
{
....
strncpy(Quizfragen->Frage,sEingabe, maxLEN_F_A);
}
When you write
memset(&ptrQuizFragen,0,maxFragen*sizeof(Fragenfeld));
you're saying "please set a lot of of bytes, starting at the address of the pointer variable ptrQuizFragen, to zero." Notice that this is different than saying "please set a lot of bytes, starting at the beginning of the array pointed at by ptrQuizFragen, to zero." This means the bytes are getting written to the wrong place, which is what's causing your segfault.
Graphically, the setup looks something like this:
ptrQuizFragen
+-----------+
| |
+-----------+
|
v
+-----------+-----------+-----------+ ... +-----------+
| | | | | |
+-----------+-----------+-----------+ ... +-----------+
QuizFragen
The line you've written puts the bytes starting where ptrQuizFragen is located in memory, which does this:
ptrQuizFragen
+-----------+
| 00000000000000000000000000000000000 ... 000000000000 (oops!)
+-----------+
+-----------+-----------+-----------+ ... +-----------+
| | | | | |
+-----------+-----------+-----------+ ... +-----------+
QuizFragen
The line you want is
memset(ptrQuizFragen, 0, maxFragen * sizeof(Fragenfeld));
which says to put the bytes at the memory location pointed at by ptrQuizFragen. That would do this:
ptrQuizFragen
+-----------+
| |
+-----------+
|
v
+-----------+-----------+-----------+ ... +-----------+
| 000000000 | 000000000 | 000000000 | | 000000000 |
+-----------+-----------+-----------+ ... +-----------+
QuizFragen
This ...
memset(&ptrQuizFragen,0,maxFragen*sizeof(Fragenfeld));
... requests that the memory starting at the address of variable ptrQuizFragen be written, but what you want is that memory at the location to which the pointer points is written:
memset(ptrQuizFragen, 0, maxFragen*sizeof(Fragenfeld));
Alternatively, for the same reason that you can initialize ptrQuizFragen as you do, you could also do away with it altogether:
memset(QuizFragen, 0, maxFragen*sizeof(Fragenfeld));
Additionally, it would be clearer to express the wanted size directly in terms of the object being written to:
memset(QuizFragen, 0, sizeof(QuizFragen));
However, if this is for one-time initialization then I would not use memset at all:
Fragenfeld QuizFragen[maxFragen] = {0};
Although that's valid C with well-defined sematics, some compilers may warn. If yours does, and that makes you uncomfortable, then one alternative would be to expand a bit to
Fragenfeld QuizFragen[maxFragen] = { { {0}, {0} } };

Why is the following code susceptible to heap overflow attack

I'm new to cyber security, and I am trying to understand why the following code is susceptible to a heap overflow attack...
struct data {
char name[128];
};
struct fp {
int (*fp)();
};
void printName() {
printf("Printing function...\n");
}
int main(int argc, char **argv) {
struct data *d;
struct fp *f;
d = malloc(sizeof(struct data));
f = malloc(sizeof(struct fp));
f->fp = printName;
read(stdin,d->name,256);
f->fp();
}
Is it because of the read(stdin, d->name, 256) as it is reading more than the allocated buffer size of 128 for char name in struct data?
Any help would be great
A heap overflow attack is similar to a buffer overflow attack, except instead of overwriting values in the stack, the attacker tramples data in the heap.
Notice in your code that there are two dynamically allocated values:
d = malloc(sizeof(struct data));
f = malloc(sizeof(struct fp));
So d now holds the address of a 128-byte chunk of memory in the heap, while f holds the address of an 8-byte (assuming a 64-bit machine) chunk of memory. Theoretically, these two addresses could be nowhere near each other, but since they're both relatively small, it's likely that the OS allocated one larger chunk of contiguous memory and gave you pointers that are next to each other.
So once you run f->fp = printName;, your heap looks something like this:
Note: Each row is 8 bytes wide
| |
+------------------------+
f -> | <Address of printName> |
+------------------------+
| ▲ |
| 11 more rows |
| not shown |
| |
d -> | <Uninitialized data> |
+------------------------+
| |
Your initial assessment of where the vulnerability comes from is correct. d points to 128 bytes of memory, but you let the user write 256 bytes to that area. C has no mechanism for bounds checking, so the compiler is perfectly happy to let you write past the edge of the d memory. If f is right next to d, you'll fall over the edge of d and into f. Now, an attacker has the ability to modify the contents of f just by writing to d.
To exploit this vulnerability, an attacker feeds the address of some code that they've written to d by repeating it for all 256 bytes of input. If the attacker has stored some malicious code at address 0xbadc0de, they feed in 0xbadc0de to stdin 32 times (256 bytes) so that the heap gets overwritten.
| 0xbadc0de |
+-------------+
f -> | 0xbadc0de |
+-------------+
| ... |
| 0xbadc0de |
| 0xbadc0de |
d -> | 0xbadc0de |
+-------------+
| |
Then, your code reaches the line
f->fp();
which is a function call using the address stored in f. The machine goes to memory location f and retrieves the value stored there, which is now the address of the attacker's malicious code. Since we're calling it as a function, the machine now jumps to that address and begins executing the code stored there, and now you've got a lovely arbitrary code execution attack vector on your hands.

can pointers exist outside their scope

why does the pointer "a" points to the correct location when i call the function for the second time
because during the second function call to "cr" the statements in the if block will not be executed so how the hell does the pointer "a" remember its previous location even though its not a static variable
code:
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
typedef struct heavy{
int data;
struct heavy *nxt;
}ode;
void cr(ode**);
void prin(ode*);
int main()
{
ode*head=NULL;
cr(&head);cr(&head);
prin(head);
getch();
return 0;
}
void cr(ode**p)
{
ode*temp,*a;
temp=*p;
if(temp==NULL)
{
a=(ode*)malloc(sizeof(ode));
a->data=1;
a->nxt=(ode*)malloc(sizeof(ode));
*p=a;
a=a->nxt;
a->nxt=NULL;
}else{
a->data=2;
a->nxt=NULL;
}
}
void prin(ode*head)
{
if(head==NULL)
printf("list is empty");
while(head!=NULL)
{
printf("%d",head->data);
head=head->nxt;
}
}
When you don't assign any value to a local variable (in this case we're talking about a) the program will behave in an unpredictable way, thus we say undefined behavior. This means that your program work correctly just by chance, and you should always remember to assign values before using the variables.
In particular, in this case I can guess why it's working every time you run it, and it has to do with how function calls work in C. Let me explain.
When we make a call to a function, a new frame (layer) in the stack (a place in memory where local variables and other "local-ish" things are stored). As you can expect from what I just said, a stack is organized in layers. Let me expose an example.
If in a particular function called George() I declare and use 2 local variables
int George(){
int a;
int b;
a = 5;
return 0;
}
the compiler will know that space for 2 variables is needed, so when I call the function it will reserve space for those 2 local variables to be stored. The new stack frame will be something like:
| 'a': ____ | <-- 4 bytes space for variable a
| 'b': ____ | <-- 4 bytes space for variable b
|-----------|
(While keeping in mind that this is not a realistic representation of the stack, it's good enough to explain what's going on)
Those spaces reserved for the values of the variables are NOT set to a default value, they contain what there was in memory before (and right now we can't make any guess).
When I call this function from another function (i.e. main) a stack frame with that shape will be added (push) to the stack:
int main(){
int hello = 7;
int hey;
hey = George(); // Here we make the function call
return 0;
}
The stack will then be something like:
STACK:
| 'a': ____ | <- 'George' stack frame, containing
| 'b': ____ | local variables of George
|--------------|
| 'hello': 7 | <- 'main' stack frame, containing
| 'hey': ____ | local variables of main
|--------------|
After the 3rd line of George, just before the return, the stack will be:
STACK:
| 'a': 5 | <- Variable a has been set to 5
| 'b': ____ |
|--------------|
| 'hello': 7 |
| 'hey': ____ |
|--------------|
and then there will be a return. Here, the stack is pop'd, which means a frame is deleted (we are returning in the main function "domain", so we discard local variables of George).
STACK:
| 'hello': 7 | <- 'main' stack frame, with hey replaced with
| 'hey': 0 | George return value (0)
|--------------|
And everything works fine, BUT the memory we pop'd just right now is not set to 0 or some other default value. It stays like that until some other program overrides it. Which means that, while we are not using those values anymore, they're probably still there.
In this state, if we call George another time, we will have our stack pushed another time:
STACK:
| 'a': ____ | <- 'a' address is in the same position
| 'b': ____ | where there was the 'a' in the previous
|--------------| function call to Giorgio
| 'hello': 7 |
| 'hey': ____ |
|--------------|
In this state, if we don't assign any value to a it will (probably) contain the value that the a had on the previous function call, because the 'new' a has the same address of the 'previous' a, because the function called is the same and there was no other function call in between that could override the previous value. If we do so, before we assign any value to the new local variable a, it contains 5.
The same happens to your program when you run
cr(&head);
cr(&head);
twice, one before the other. The value of your local variable a is probably kept unchanged.
Anyway, explanation apart, NEVER use this kind of behaviors in your code. This is a very very bad way of programming, and the outcome is usually unpredictable.
I hope my explanation was not too bad.

Assigning same values to 2 pointers, not equalising their references (pointers in C)

printf("%p\n\n", element); //0x1000020c0
table->head->element = element;
printf("%p\n\n", table->head->element); //0x1000020c0
I have a pointer to a struct which points to another struct where is char* variable is stored. The problem is a pointer(char * element) which is sent to this method is modified somewhere else, and I don't want those modifications to be affected in table->head->element. Simply said I want to make their values equal, not the reference.
I knew that we can assign same values to 2 pointers like this: *p1=*p2. However, I am not sure how to do that with structs, I tried:
*(table->head->element) = *element;
But it did not work.
I hope I could clarify my question.
If you want the pointed-to string by a copy, not simply a reference, you'll need to strcpy() it into some new memory. e.g.
int len = strlen(element);
table->head->element = malloc(len+1); // +1 for string-terminating null
strcpy(table->head->element, element);
(or use strdup() for a one-line solution, as pointed out in R Sahu's reply).
Responding to OP's comments in the answer by #GrahamPerks.
That will work, but I don't want using additional coping, because we can do it with pointer
Let's say the memory used by element looks like below:
element +---------+ +---+---+---+---+---+---+---+---+------+
| ptr1 | -> | a | | s | t | r | i | n | g | '\0' |
+---------+ +---+---+---+---+---+---+---+---+------+
If you use:
table->head->element = element;
the value of table->head->element is ptr1.
If some time later, you went ahead and changed the contents of ptr1 through element, such as by using:
fscanf(file, "%s", element);
You could end up with:
element +---------+ +---+---+---+---+---+---+---+---+---+---+------+
| ptr1 | -> | n | e | w | | s | t | r | i | n | g | '\0' |
+---------+ +---+---+---+---+---+---+---+---+---+---+------+
At that point, the string that you see from table->head->element is "new string", not "a string".
This is what happens when you don't copy the contents of element but just copy the pointer value of element.
If you want the value of table->head->element to remain "a string" while the value of element changes, you have to copy the contents of element using
int len = strlen(element);
table->head->element = malloc(len+1);
strcpy(table->head->element, element);
or, if your complier supports strdup, by using
table->head->element = strdup(element);

Dynamically allocating array explain

This is sample code my teacher showed us about "How to dynamically allocate an array in C?". But I don't fully understand this. Here is the code:
int k;
int** test;
printf("Enter a value for k: ");
scanf("%d", &k);
test = (int **)malloc(k * sizeof(int*));
for (i = 0; i < k; i++) {
test[i] = (int*)malloc(k * sizeof(int)); //Initialize all the values
}
I thought in C, to define an array you had to put the [] after the name, so what exactly is int** test; isn't it just a pointer to a pointer? And the malloc() line is also really confusing me.....
According to declaration int** test; , test is pointer to pointer, and the code pice allocating memory for a matrix of int values dynamically using malloc function.
Statement:
test = (int **)malloc(k * sizeof(int*));
// ^^------^^-------
// allocate for k int* values
Allocate continue memory for k pointers to int (int*). So suppose if k = 4 then you gets something like:
temp 343 347 351 355
+----+ +----+----+----+----+
|343 |---►| ? | ? | ? | ? |
+----+ +----+----+----+----+
I am assuming addresses are of four bytes and ? means garbage values.
temp variable assigned returned address by malloc, malloc allocates continues memory blocks of size = k * sizeof(int**) that is in my example = 16 bytes.
In the for loop you allocate memory for k int and assign returned address to temp[i] (location of previously allocated array).
test[i] = (int*)malloc(k * sizeof(int)); //Initialize all the values
// ^^-----^^----------
// allocate for k int values
Note: the expression temp[i] == *(temp + i). So in for loop in each iterations you allocate memory for an array of k int values that looks something like below:
First malloc For loop
--------------- ------------------
temp
+-----+
| 343 |--+
+-----+ |
▼ 201 205 209 213
+--------+ +-----+-----+-----+-----+
343 | |= *(temp + 0) | ? | ? | ? | ? | //for i = 0
|temp[0] |-------| +-----+-----+-----+-----+
| 201 | +-----------▲
+--------+ 502 506 510 514
| | +-----+-----+-----+-----+
347 |temp[1] |= *(temp + 1) | ? | ? | ? | ? | //for i = 1
| 502 |-------| +-----+-----+-----+-----+
+--------+ +-----------▲
| | 43 48 52 56
351 | 43 | +-----+-----+-----+-----+
|temp[2] |= *(temp + 2) | ? | ? | ? | ? | //for i = 2
| |-------| +-----+-----+-----+-----+
+--------+ +-----------▲
355 | |
| 9002 | 9002 9006 9010 9014
|temp[3] | +-----+-----+-----+-----+
| |= *(temp + 3) | ? | ? | ? | ? | //for i = 3
+--------+ | +-----+-----+-----+-----+
+-----------▲
Again ? means garbage values.
Additional points:
1) You are casting returned address by malloc but in C you should avoid it. Read Do I cast the result of malloc? just do as follows:
test = malloc(k* sizeof(int*));
for (i = 0; i < k; i++){
test[i] = malloc(k * sizeof(int));
}
2) If you are allocating memory dynamically, you need to free memory explicitly when your work done with that (after freeing dynamically allocated memory you can't access that memory). Steps to free memory for test will be as follows:
for (i = 0; i < k; i++){
free(test[i]);
}
free(test);
3) This is one way to allocate memory for 2D matrix as array of arrays if you wants to allocate completely continues memory for all arrays check this answer: Allocate memory 2d array in function C
4) If the description helps and you want to learn for 3D allocation Check this answer: Matrix of String or/ 3D char array
Remember that arrays decays to pointers, and can be used as pointers. And that pointers can be used as arrays. In fact, indexing an array can be seen as a form or pointer arithmetics. For example
int a[3] = { 1, 2, 3 }; /* Define and initialize an array */
printf("a[1] = %d\n", a[1]); /* Use array indexing */
printf("*(a + 1) = %d\n", *(a + 1)); /* Use pointer arithmetic */
Both outputs above will print the second (index 1) item in the array.
The same way is true about pointers, they can be used with pointer arithmetic, or used with array indexing.
From the above, you can think of a pointer-to-pointer-to.type as an array-of-arrays-of-type. But that's not the whole truth, as they are stored differently in memory. So you can not pass an array-of-arrays as argument to a function which expects a pointer-to-pointer. You can however, after you initialized it, use a pointer-to-pointer with array indexing like normal pointers.
malloc is used to dynamically allocate memory to the test variable think of the * as an array and ** as an array of arrays but rather than passing by value the pointers are used to reference the memory address of the variable. When malloc is called you are allocating memory to the test variable by getting the size of an integer and multiplying by the number of ints the user supplies, because this is not known before the user enters this.
Yes it is perfectly Ok. test is pointer to pointer and so test[i] which is equivalent to writing test + i will be a pointer. For better understanding please have a look on this c - FAQ.
Yes indeed, int** is a pointer to a pointer. We can also say it is an array of pointers.
test = (int **) malloc(k * sizeof(int*));
This will allocate an array of k pointers first. malloc dynamically allocates memory.
test[i] = (int*) malloc(k * sizeof(int));
This is not necessary as it is enough to
test[i] = (int*) malloc(sizeof(int*));
Here we allocate each of the array places to point to a valid memory. However for base types like int this kind of allocation makes no sense. It is usefull for larger types (structs).
Each pointer can be accessed like an array and vice versa for example following is equivalent.
int a;
test[i] = &a;
(test + i) = &a;
This could be array test in memory that is allocated beginning at offset 0x10000000:
+------------+------------+
| OFFSET | POINTER |
+------------+------------+
| 0x10000000 | 0x20000000 | test[0]
+------------+------------+
| 0x10000004 | 0x30000000 | test[1]
+------------+------------+
| ... | ...
Each element (in this example 0x2000000 and 0x30000000) are pointers to another allocated memory.
+------------+------------+
| OFFSET | VALUE |
+------------+------------+
| 0x20000000 | 0x00000001 | *(test[0]) = 1
+------------+------------+
| ...
+------------+------------+
| 0x30000000 | 0x00000002 | *(test[1]) = 2
+------------+------------+
| ...
Each of the values contains space for sizeof(int) only.
In this example, test[0][0] would be equivalent to *(test[0]), however test[0][1] would not be valid since it would access memory that was not allocted.
For every type T there exists a type “pointer to T”.
Variables can be declared as being pointers to values of various types, by means of the * type declarator. To declare a variable as a pointer, precede its name with an asterisk.
Hence "for every type T" also applies to pointer types there exists multi-indirect pointers like char** or int*** and so on. There exists also "pointer to array" types, but they are less common than "array of pointer" (http://en.wikipedia.org/wiki/C_data_types)
so int** test declares an array of pointers which points to "int arrays"
in the line test = (int **)malloc(k*sizeof(int*)); puts enough memory aside for k amount of (int*)'s
so there are k amount of pointers to, each pointing to...
test[i] = (int*)malloc(k * sizeof(int)); (each pointer points to an array with the size of k amounts of ints)
Summary...
int** test; is made up of k amount of pointers each pointing to k amount of ints.
int** is a pointer to a pointer of int. take a look at "right-left" rule

Resources