Free an array of struct - c

#include<stdlib.h>
#include <stdio.h>
#include <string.h>
struct t {
int value;
};
int main (void) {
struct t *a = malloc(6*sizeof(struct t));
struct t *b = malloc(sizeof(struct t));
struct t *c = malloc(sizeof(struct t));
c->value = 100;
struct t *d = malloc(sizeof(struct t));
d->value = 100;
struct t *e = malloc(sizeof(struct t));
e->value = 100;
memcpy(b, a, sizeof(*a));
int j = 0;
while (j<6){
a[j] = *c;
j++;
}
int t = 0;
while(t < 6){
free(&a[t]);
t++;
}
free(a);
}
I'm trying to free the elements inside the array one by one. But this code cannot run so I think there might something wrong with free inside the second while loop. After I changed the second while loop to:
while(t < 6){
printf("%d",a[t].value);
t++;
}
It will run. Any idea how can I free those elements?
Thanks!

I'm trying to free the elements inside the array one by one. But this code cannot run so I think there might something wrong with free inside the second while loop.
Yes, what's wrong is the attempt to free the elements one by one.
You cannot free allocated memory in different divisions than it was allocated in. The argument to free() must be a pointer value that was previously obtained from an allocation function (and not since freed). The free() call will then free the entire block. It cannot see any subdivisions of that block that you may be using, and it would be unlikely to be able to honor them even if it could see them.
Any idea how can I free those elements?
Free the whole block at once, after you're done with all the data within. That is, just
free(a);
(And also, free(b), free(c), etc.)

One free per malloc'd block.
When you malloc, you are not grabbing memory for each struct. You are grabbing one block (per malloc call) that happens to be large enough to fit 6 structs for a and 1 struct each for the others. You can only free each block of this block at once. In this case you should be freeing a through e (which are addresses returned by malloc assuming you had enough memory).
You could if you really needed to, malloc an array of struct * then malloc blocks into those struct *, but why would you in this case where the struct is small and easily copied?

The key is this: When you allocate a block of memory, malloc (calloc or realloc) will return a pointer to the beginning address in that block. You have 2 responsibilities regarding any block of memory allocated: (1) always preserve a pointer to the starting address for the block of memory so, (2) it can be freed when it is no longer needed. free() must be passed the same address returned by malloc().
You can not provide an address from the middle of the allocated block to free(). Why? Because that will not be an address originally returned by a previous call to malloc, calloc or realloc. That is a requirement, see the man-page for free() (man 3 malloc)
The free() function frees the memory space pointed to by ptr, which must have
been returned by a previous call to malloc(), calloc(), or realloc().
So you can only make a call to free() providing a pointer holding an address that was previously allocated and returned by malloc, calloc or realloc. In your case that is a, not &a[1] ... &a[5].

Related

How can i free the pointer i used? is it possible to free pointers after use?

#include<stdio.h>
void trimSpace(char *s) {
char *t = s;
while(s = t, t[0] == ' '){ //checks initial array is space
while (*(s) = *(s+1),*s++ != '\0') { . //if so then move all data to left
}
}
printf("%s",s);
//free(s);
//free(t);
}
int main(){
char s[] = " abcdefghijklmnopqrstuvwxyz";
trimSpace(s);
return 0;
}
is it possible to free the pointers. i am getting
ERROR: Invalid free() / delete / delete[] / realloc()
(Stopped running after the first error. Please fix your code.)
The free function is used to deallocate memory that was returned from malloc and return it to the heap's available space. Only a pointer returned from malloc, calloc, or realloc may be passed to free.
You're not allocating memory dynamically, so no need to call free.
A pointer is a variable capable of storing an address of another variable i.e. it is like other variables. Static memory allocation is done at compile time and stack is used to manage this. As soon as the scope of variable is over, memory is freed. Only the dynamic memory allocated during runtime using heap can be freed using the free() function

How can I use free when I used ** ( double pointer )?

STUDENT ** list=NULL;
char *getid;
getid =(char*)malloc(sizeof(char) * 8);
printf("How many student? ");
int menuNum,num=0;
scanf("%d",&num);
list=(STUDENT**)malloc(num*sizeof(STUDENT*));
I used pointer like this.
As I learned from the professor, before finishing my code, I ought to use free() function to retrieve the allocated memory again.
Here s what i wanna ask you.
I learned that If i wanna use free() about (char *getid)
I know I should write
free(getid);
then How can I use free about
STUDENT ** list = NULL ; // **It's about struct**
Should I use like
free(list);
or
free(*list);
I think the former is right, but when I write like the latter, there's no error on my X-code.
Could you tell me about it ?
You should use:
free(list);
but when I write like free(*list);, there's no error on my X-code
That's why *list does not deallocate anything, since nothing is allocated there. However, your program suffers from a memory leak that way, since the memory pointed to by the double pointer named list is not free'd. However, you are just (un)lucky not to see your program crash.
If you used Valgrind though, you would see the memory leak.
Should I write malloc and write free() immediately? not in the end of the line?
No. You first allocate the memory dynamically with malloc(), then you use this memory (initialize, access, etc.) and when you do not need the memory anymore, and only then, you deallocate it with free().
However, if you had dynamically allocated space for list[i], then you should do:
free(list[i]);
free(list);
where the order matters, since you do not want to have tangling pointers!
Maybe my example on dynamically allocated a 2D array will more explanatory on this, even though it's a different data structure than a list.
PS: We don't cast what malloc returns.
You should free any memory allocated by malloc with free...
as you figured out, you requested 8 bytes of memory and saved the Pointer to it to your symbol getid (getid =(char*)malloc(sizeof(char) * 8);)
as for your list, this is a bit trickier:
You actually allocating a list of pointers that should point to other memory locations (those might be dynamically allocated as well)
list=(STUDENT**)malloc(num*sizeof(STUDENT*)); size of num pointers
Allocates the space for the list and saves the pointer to it at symbol list.
I'd remind that the memory allocated doesn't have to come initialized from the OS, so we should initialize it.
for(int i=0; i<num; i++)
{
list[i] = NULL;
}
You could also use memset(list, NULL, num * sizeof(STUDENT*)).
and you are very much correct you should free its memory by free(list),
But you should free the items in the list BEFORE you free the list of pointers itself. (again, if the items were dynamically allocated!)
for(int i=0; i<num; i++)
{
if(list[i] != NULL) // only if allocated.
{
free(list[i]); // free the element # position i
list[i] = NULL;
}
}

Freeing malloced structure in a function

I'm creating a source files containing buffer functionality that I want to use for my other library that I'm creating.
It is working correctly but I'm having trouble getting rid of the buffer structure that I'm creating in one of the functions. The following snippets should help illustrate my problem:
C header:
//dbuffer.h
...
typedef struct{
char *pStorage;
int *pPosition;
int next_position;
int number_of_strings;
int total_size;
}DBUFF;
...
C source:
//dbuffer.c
...
DBUFF* dbuffer_init(char *init_pArray)
{
//Find out how many elements the array contains
int size = sizeof_pArray(init_pArray);
//Initialize buffer structure
DBUFF *buffer = malloc(sizeof(DBUFF));
//Initialize the storage
buffer->pStorage = malloc( (sizeof(char)) * (size) );
strncpy( &(buffer->pStorage)[0] , &init_pArray[0] , size);
buffer->number_of_strings = 1;
buffer->total_size = size;
buffer->next_position = size; //size is the next position because array allocates elements from 0 to (size-1)
//Initialize the position tracker which keeps record of starting position for each string
buffer->pPosition = malloc(sizeof(int) * buffer->number_of_strings );
*(buffer->pPosition + (buffer->number_of_strings -1) ) = 0;
return buffer;
}
void dbuffer_destroy(DBUFF *buffer)
{
free(buffer->pStorage);
free(buffer);
}
...
Main:
#include <stdio.h>
#include <stdlib.h>
#include "dbuffer.h"
int main(int argc, char** argv)
{
DBUFF *buff;
buff = dbuffer_init("Bring the action");
dbuffer_add(buff, "Bring the apostles");
printf("BUFFER CONTENTS: ");
dbuffer_print(buff);
dbuffer_destroy(buff);
// Looks like it has been succesfully freed because output is garbage
printf("%s\n", buff->pStorage);
//Why am I still able to access struct contents after the pointer has been freed ?
printf("buff total size: %d\n", buff->total_size);
return (EXIT_SUCCESS);
}
Output:
BUFFER CONTENTS: Bring the action/0Bring the apostles/0
��/�
buff total size: 36
RUN SUCCESSFUL (total time: 94ms)
Question:
Why am I still able to access struct contents using the line below after the pointer to the struct has been freed ?
printf("buff total size: %d\n", buff->total_size);
Once you've called free() on the allocated pointer, attempt to make use of the pointer invokes undefined behavior. You should not be doing that.
To quote C11 standard, chapter §7.22.3.4, free() function
The free() function causes the space pointed to by ptr to be deallocated, that is, made
available for further allocation. [..]
It never say's anything about a cleanup, which you might be (wrongly) expecting.
Just to add clarity, calling free() does not always actually free up the allocated physical memory. It just enables that pointer (memory space) to be allocated again (returning the same pointer, for example) for successive calls to malloc() and family. After calling free(), that pointer is not supposed to be used from your program anymore but C standard does not guarantee of a cleanup of the allocated memory.
If any attempt is made to read memory that has been freed can crash your program. Or they might not. As far as the language is concerned, its undefined behaviour.
Your compiler won't warn you about it(or stop you from accessing it). But clearly don't do this after calling free -
printf("buff total size: %d\n", buff->total_size);
As a good practice you can set the freed pointer to NULL .
free() call will just mark the memory in heap as available for use. So you still have the pointer pointing to this memory location but it's not available anymore for you. Thus, the next call to malloc() is likely to assign this memory to the new reservation.
To void this situations normally once you free() the memory allocated to a pointer you should set it to NULL. De-referencing NULL is UB also but at least when debugging you can see tha pointer should not be used because it's not pointing to a valid memory address.
[too long for a comment]
To allow your "destructor" to set the pointer passed to NULL modify your code like this:
void dbuffer_destroy(DBUFF ** buffer)
{
if ((NULL == buffer) || (NULL == *buffer))
{
return;
}
free((*buffer)->pPosition);
free((*buffer)->pStorage);
free(*buffer);
*buffer = NULL;
}
and call it like this:
...
dbuffer_destroy(&buff);
...

Two pointers are pointing to same memory address, how to avoid memory leak in case freeing of these two happens at independence place?

int *a = malloc(40);
int *b;
b=a;
if( *some conditions* )
free(a);
// I know that 'a' has been allocated this chunk of memory X times
// and free(a) has been called less than X times.
I have no idea of that condition, so don't know whether 'a' has been freed or not! So now how would I be sure if 'b' i.e. 'a' has been freed or not.
If you want to make sure that subsequent calls of free on a pointer to dynamically allocated memory will not do any harm, you should assign NULL to that pointer. Because (emphasis added):
The free() function frees the memory space pointed to by ptr, which must have been returned by a previous call to malloc(), calloc() or realloc(). Otherwise, or if free(ptr) has already been called before, undefined behavior occurs. If ptr is NULL, no operation is performed.
If you want to make sure that pointer b will always refer to the same object the other pointer a points at, you could turn b into a pointer to a instead (and dereference it each time you need to use it):
#include <stdio.h>
#include <stdlib.h>
int main() {
/* dynamically allocate some memory */
int *a = malloc(40);
/* b is a pointer to a pointer to an int */
int **b;
/* make b point to a */
b = &a;
if ( 1 ) {
/* free memory and assign NULL to the pointer */
free(a);
a = NULL;
}
/* nothing bad will happen when we dereference b now */
printf("%p\n", *b);
/* nothing bad will happen when we free the memory region
where the pointer b points to points to */
free(*b);
}
Another thing on memory leaks. There will be no memory leaked when you double-free the memory. In that case you will stumble into undefined behavior, in which case anything could happen. Simply because you shall not access memory regions that are not your own (anymore) (c.f., this great post).
Instead, you will leak memory when you loose the reference to a block of dynamically allocated memory. For example:
/* allocate some memory */
int *a = malloc(40);
/* reassign a without free-ing the memory before : you now have leaked memory */
a = malloc(40);
The best option is not having two pointers, pointing to the same place, which are freed independently.
But if that's really what you need, then you need a reference count.
The following code implements a very simple reference count mechanism.
When you assign a second pointer to your data, you should use clone_x to increment the reference count.
Each time you free, use free_x, and it will free just once.
Note that this code isn't multithread-safe. If your code is multi-threaded, you need atomic operations, and you need to be very careful with how you use them.
struct x {
int refcount;
int payload;
};
struct x *create_x(int payload) {
struct x *newx = malloc(sizeof(*newx));
if (!newx) return NULL;
newx->payload = payload;
newx->refcount = 1;
return newx;
}
void clone_x(struct x *myx) {
myx->refcount++;
}
void free_x(struct x *oldx) {
oldx->refcount--;
if (oldx->refcount == 0) {
free(oldx);
}
}
You can't. When free(a) is called it is no longer safe to access that memory.
Even if you malloc() new memory and assign the result to a, that memory could be anywhere.
What you're trying to do will not work.
every allocated memory block should have an 'owner', a or b, if a is the owner, pointer b should not release that block, vice versa.

Redefining free memory function in C

I'm redefining memory functions in C and I wonder if this idea could work as implementation for the free() function:
typedef struct _mem_dictionary
{
void *addr;
size_t size;
} mem_dictionary;
mem_dictionary *dictionary = NULL; //array of memory dictionaries
int dictionary_ct = 0; //dictionary struct counter
void *malloc(size_t size)
{
void *return_ptr = (void *) sbrk(size);
if (dictionary == NULL)
dictionary = (void *) sbrk(1024 * sizeof(mem_dictionary));
dictionary[dictionary_ct].addr = return_ptr;
dictionary[dictionary_ct].size = size;
dictionary_ct++;
printf("malloc(): %p assigned memory\n",return_ptr);
return return_ptr;
}
void free(void *ptr)
{
size_t i;
int flag = 0;
for(i = 0; i < dictionary_ct ; i++){
if(dictionary[i].addr == ptr){
dictionary[i].addr=NULL;
dictionary[i].size = 0;
flag = 1;
break;
}
}
if(!flag){
printf("Remember to free!\n");
}
}
Thanks in advance!
No, it will not. The address you are "freeing" is effectively lost after such a call. How would you ever know that the particular chunk of memory is again available for allocation?
There has been a lot of research in this area, here is some overview - Fast Memory Allocation in Dr. Dobbs.
Edit 0:
You are wrong about sbrk(2) - it's not a "better malloc" and you cannot use it as such. That system call modifies end of process data segment.
Few things:
Where do you allocate the memory for the dictionary?
How do you allocate the memory that dictionary->addr is pointing at? Without having the code for your malloc it is not visible if your free would work.
Unless in your malloc function you're going through each and every memory address available to the process to check if it is not used by your dictionary, merely the assignment dictionary[i].addr=NULL would not "free" the memory, and definitely not keep it for reuse.
BTW, the printf function in your version of free would print Remember to free! when the user calls free on a pointer that is supposedly not allocated, right? Then why "remember to free"?
Edit:
So with that malloc function, no, your free does not free the memory. First of all, you're losing the address of the memory, so every time you call this malloc you're actually pushing the process break a little further, and never reuse freed memory locations. One way to solve this is to somehow keep track of locations that you have "freed" so that next time that malloc is called, you can check if you have enough available memory already allocated to the process, and then reuse those locations. Also, remember that sbrk is a wrapper around brk which is an expensive system call, you should optimize your malloc so that a big chunk of memory is requested from OS using sbrk and then just keep track of which part you're using, and which part is available.

Resources