Arrays of struct in c [duplicate] - c

This question already has answers here:
C - freeing structs
(7 answers)
Closed 5 years ago.
struct a {
int a;
int b;
};
struct a* ptr = NULL;
In main
ptr = malloc(5 * sizeof(struct a ));
//assume is 5 is from user
Assign values to ptr[0].a and ptr[0].b, similarly to all 5 block
free(ptr);
Is free (ptr) enough to free all arrays of struct? Or should i free explicitly? If so, how? Thanks.

You need to free whatever is returned by any memory management function. For allocations that are nested you need to do it reverse order of the way they are allocated. (Typical example would be creation of jagged array)
void free(void *ptr);
From 7.22.3.2p2
The free function causes the space pointed to by ptr to be deallocated, that is, made available for further allocation. If ptr is a null pointer, no action occurs. Otherwise, if the argument does not match a pointer earlier returned by a memory management function, or if the space has been deallocated by a call to free or realloc, the behavior is undefined.
In your case free(ptr) would be enough to free the dynamically allocated memory. If it contained some pointer variable to which we assigned address of dynamically allocated memory then you would need to free then first and then this ptr variable.

Related

C pointer + free: Abort signal from abort(3) (SIGABRT) [duplicate]

This question already has answers here:
Why exactly should I not call free() on variables not allocated by malloc()?
(7 answers)
Closed 4 years ago.
I have written the following code in C:
#include <stdio.h>
#include <stdlib.h>
int main (int argc , char *argv[]) {
int * ptr = (int *)malloc(sizeof(int));
int three = 3;
ptr = &three;
free(ptr);
return EXIT_SUCCESS;
}
When I execute I get following error:
Abort signal from abort(3) (SIGABRT).
Could you help me find my mistake?
Thank you!
What you have is undefined behavior. The C11 standard states thus:
7.22.3.3 The free function
...
2 The free function causes the space pointed to by ptr to be deallocated, that is, made
available for further allocation. If ptr is a null pointer, no action occurs. Otherwise, if
the argument does not match a pointer earlier returned by a memory management
function, or if the space has been deallocated by a call to free or realloc, the
behavior is undefined.
In your example the argument of free is &three which is not a pointer returned by a memory management function and therefore you have the behavior you see.
When you call malloc a pointer to memory chunk of requested size is returned (on success). This memory chunk is allocated form heap, and you can use that pointer to un-allocate it by calling free later.
Local variables are allocated memory from stack.
What you are doing here is allocating a memory chunk from heap:
int * ptr = (int *)malloc(sizeof(int));
and then overwriting then overwriting ptr with address of a local variable who's memory resides on stack.
ptr = &three;
and then attempting to free that memory:
free(ptr);
which is undefined behaviour.

Reassigning to a pointer variable after freeing it [duplicate]

This question already has answers here:
Reusing freed pointers in C
(4 answers)
Closed 5 years ago.
Is this legal to do? Can you assign ptr to something after it has been freed?
int * ptr = (int*) malloc(sizeof(int));
free(ptr);
ptr = (int *) malloc(sizeof(int));
You aren't reassigning the pointer after freeing it, you're just reusing the ptr variable. This is perfectly fine.
First of all, as I mentioned in the comments, please see this discussion on why not to cast the return value of malloc() and family in C..
That said, yes, the (re)-assignment is fine here.
Actually, the question wording
Can you assign ptr to something after it has been freed?
should read
Can you assign ptr with something after it has been freed?
Guess what, the assignment without free-ing is also legal as per C, but it will create a memory leak as a side effect as the variable ptr was holding the return value of a memory allocator function and you need to free the memory once you're done using it. If, you re-assign the pointer without keeping a copy of the pointer, you'll lose the access to the memory allocated by allocator function and will have no ways to free() it.
In case the pointer was holding an address of statically allocated variable, you don't get to (nned to) free it and direct re-assignment is perfectly fine. think of this below snippet.
int x = 5, y = 10;
int * p = &x;
//do something with p
p = &y; //this is fine, just a re-assignment.
Yes. it is a valid in C language.
Related stack overflow question for more information: Reusing freed pointers in C
According to cwe.mitre.org:
In this scenario, the memory in question is allocated to another
pointer validly at some point after it has been freed. The original
pointer to the freed memory is used again and points to somewhere
within the new allocation. As the data is changed, it corrupts the
validly used memory; this induces undefined behavior in the process.
Can you assign ptr to something after it has been freed?
int * ptr = (int*) malloc(sizeof(int)); /* line 1 */
free(ptr); /* line 2 */
ptr = (int *) malloc(sizeof(int)); /* line 3 */
Taking your question as:
"Is it legal to assign the address of freshly, dynamically allocated memory to a pointer (line 3), after the memory this pointer pointed to from a previous dynamical allocation (line 1) had been freed (line2)?"
Then this answer is yes.
Running line 3 would also be valid without having run line 2. Still, if not calling free() (line 2), the value assigned to ptr (line 1) is overwritten (line 3), and with this the possibility to call free() on ptr's initial value is lost, which in turn leaves the program with leaking exactly this memory allocated initially.
Is this legal to do? Can you assign ptr to something after it has been freed?
Yes, this is legal. ptr can be reassigned as many times as you want. Freeing that pointer is not necessary for reassigning it, for example
int * ptr = malloc(sizeof(int));
int *temp_ptr = ptr; // temp_ptr is pointing to the location ptr is pointing
ptr = malloc(sizeof(int)); // ptr points to new location.
Note that you should not cast the return value of malloc.
Yes you are assigning new memory on heap and its legal.
I would recommend you use realloc instead.
For the case when realloc() fails, from c11, chapter ยง7.22.3.5,
The realloc function returns ... a null pointer if the new object
could not be allocated.
and
[....] If memory for the new object cannot be allocated, the old
object is not deallocated and its value is unchanged.
The proper way of using realloc will be
ptr_new = realloc(ptr, sizeof(int)*2);
if (ptr_new == NULL)
{
free(ptr);
}
Also please read why should i not cast return value of malloc.
Yes. It is perfectly legal. ptr is a standalone variable that continues to exist regardless of its contents. Nothing happens to the memory location where ptr is stored. There is nothing to prevent you from assigning you any value to it. The correctness of the memory allocation ( malloc / realloc etc) is a different story, but there is nothing wrong with reusing a variable (a memory location) to store the address of a memory location.
When you declare a pointer it will be allocated for it a memory location. That location can be reassigned.
If you reassign it after having assigned it a value with a malloc() call and before to free() it, this is a memory leak. After free() you can reassign it and no leak will happen, do not forget to free() it again.
In fact, the operating systems that are useful programs that never finish will reassign all the time some fixed pointers toward processes, free them when the process finishes, etc.
The programming in which assignments are not allowed is called functional programming.

Range of free on malloc returned memory [duplicate]

This question already has answers here:
How much memory would be freed if pointer is changed in C?
(3 answers)
Closed 7 years ago.
Given the following line:
int *digits = (int *) malloc(3 * sizeof(int));
Say we store the values 1, 2 and 3 in locations, digits[0], digits[1], digits[2]. As follows:
digits[0] = 1;
digits[1] = 2;
digits[2] = 3;
If the following line is called:
free(++digits);
Is the entire memory range returned by malloc freed, or just the int sized block currently pointed to by digits - at that time, digits[1]? Or is the correct way, to free the entire range by iteration, i.e:
for (i = 0; i < 3; i++)
{
free(digits[i]);
}
I am trying to understand the range of a call to free. Is the entire memory chunk returned by malloc freed, or is only a sub-portion, currently referenced by the pointer digits freed?
You must free() the exact same pointer value you get from malloc(). The entire blob of memory allocated by malloc() will be freed at once.
You can't use a pointer int the middle of the buffer returned to you by malloc() to free() it, but you must pass to free() exactly what malloc() returned you.
http://linux.die.net/man/3/malloc is pretty explicit about this.
As per rule malloc provide you with chunk of memory you demanded and return you start address of the chunk. you have to use digit to free memory as the only legal way to identify the allocated memory is pointer returned in your case it is digits

Free a NULL pointer [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Does free(ptr) where ptr is NULL corrupt memory?
Is it good practice to free a NULL pointer in C?
I have a question concerning freeing a null pointer.
char *p = NULL;
free(p);
Could the free(NULL) cause a crash?
Or does it depend on the compiler?
From man page of free
void free(void *ptr);
The free() function deallocates the memory allocation pointed to by
ptr. If ptr is a NULL pointer, no operation is performed.
If you want to get confirmation from C manual itself
The free function causes the space pointed to by ptr to be
deallocated, that is, made available for further allocation. If ptr is
a null pointer, no action occurs.
See page 313 of this document.

Where are character arrays in dynamically allocated structs stored? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
C Array Instantiation - Stack or Heap Allocation?
When dynamically allocating a struct containing a char pointer, what happens with the actual char pointer? Where is it stored?
And once the struct is freed, is the char pointer freed along with it?
For example consider the following struct:
struct mix
{
int a;
float b;
char *s;
};
typedef struct mix mix;
And then the following code that allocates memory for it:
int main()
{
mix *ptr = (mix*)malloc(sizeof(mix));
ptr->a = 3;
ptr->b = 4.5f;
ptr->s = "Hi, there, I'm just a really long string.";
free(ptr);
return 0;
}
Is *s allocated on the stack and then freed along with *ptr? I can imagine it is indeed allocated on the stack as it's not in any way dynamically allocated (unless malloc has some functionality I'm not aware of). And I guess 'going out of scope' for *s would be at the point of freeing *ptr. Or have I got it completely wrong? :)
Thanks very much!
The space for the char* member named s is allocated on the heap, along with the rest of the members of mix after the call to malloc() (whose return value you do not need to cast). The string literal to which s is assigned is not allocated on the heap or the stack, but is part of the actual binary and has static storage duration. So this:
ptr->s = "Hi, there, I'm just a really long string.";
assigns the address of the string literal to ptr->s. If you want ptr->s to point to something other than a string literal then you need to malloc() memory for it. And for every malloc() there must be a free() so ptr->s would need to be free()d before ptr is (if ptr->s is pointing to dynamically allocate memory only).
After the call to free(), dereferencing ptr is undefined behaviour.
When you dynamically allocate mix with malloc(), you are actually allocating a block of memory to store mix structure data members, i.e.
an int (a)
a float (b)
a pointer to a char (s)
And when you call free(), you just release that block.
So, you don't allocate the string, you just allocate the string pointer.
If you want to dynamically allocate the string, you must do it explicitly (with another call to malloc()), and to avoid memory leaks you should also free the string explicitly, using free().
When you malloc for ptr, memory is allocated for all members of the struct including the pointer s which is no different to memory allocated for any other member of the struct.
You are assigning a string literal to s, so it's fine which is usually stored in the read-only section. Otherwise, you'll need to malloc for the ptr->s as well and free. Since, it's a string literal, there's no need to free s here (doing so is UB).
mix* ptr is allocated on the stack. The contents that ptr point at, a variable of type mix, is allocated dynamically on the heap, including the pointer s.
Please note that s doesn't point at anything, the pointer doesn't do anything useful. You have to set it to point at something, which could be allocated anywhere. Whatever it points to is not freed when your struct is freed. In this case you set it to point at a constant string literal allocated in ROM, so you won't need to worry about that.
Is *s allocated on the stack
*s (that is, the result of dereferencing the pointer s) isn't allocated at all. Following the malloc, ptr->s is an uninitialized pointer. It doesn't point to anything, and the expression *(ptr->s) has undefined behavior until you do ptr->s = "Hi, etc".
Once you've initialized ptr->s to point to the string literal, *(ptr->s) is the first character of the string literal, so it probably exists in some data section of the executable. Nothing is dynamically allocated other than the sizeof(mix) bytes for the struct (probably 12 bytes on a 32bit implementation).
what happens with the actual char pointer? Where is it stored?
char* is also like other members, take some bytes(take 8 byte in 64 bit machine, similar to other pointer). In your case, you are allocating memory for that structure instance in heap. so the memory for this pointer also will be allocated in same heap block which is allocated for that structure instance.
Consider this code. This gives where the char* will be:
#include <stdio.h>
typedef struct
{
int a;
float b;
char *s;
}mix;
int main()
{
printf("\n%d ,float:%d, int:%d, char*:%d", sizeof(mix), sizeof(float), sizeof(int), sizeof(char*));
return 0;
}
so size of this structure is 16 bytes. consist of 4 byte integer, 4 byte float and 8 byte char*. (In 64 bit OS, char* will be 4 bytes if OS is 32 bit.)
And once the struct is freed, is the char pointer freed along with it?
Usually the block which is pointed by char* will not be freed(If it points to a block allocated by malloc()). only the structure block will be freed. we know free() needs valid address which is returned during allocation for peaceful de-allocation. If you free without freeing that char*, it will leads to memory leak.
But your case "Hi, there, I'm just a really long string.";
the above given string is string literal which is allocated in read-only section of your program.
use gcc -S Yourprogram.c
This will generate .s file. You can look at .read_only section for this string. so even you delete your structure instance, there will be no memory leak. Because you are just pointing a address which is read-only. You are not at-all allocating memory for this string.

Resources