Do I need to free structs within structs? - c

I have the following piece of code. I want to properly free all my memory. As you can see, I have a b_struct within an a_struct. I wonder whether I need to manually free the b_struct within the a_struct, and if so, what is the proper way to do it?
#include <stdlib.h>
#include <stdio.h>
struct b_struct {
int c;
};
struct a_struct {
struct b_struct b;
};
int main(int argc, char **argv)
{
struct a_struct *a;
a = calloc(1, sizeof(*a));
a->b.c = 5;
printf("Value: %d", a->b.c);
free(a);
}

I wonder whether I need to manually free the b_struct within the a_struct
No.
From the malloc(3) man page:
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().
When you allocated sizeof(struct a_struct) bytes, that includes all members of that structure, including the struct b_struct member. This struct member is no different than an int or char[] member; it's all just one contiguous block of memory to the allocator.

No. Not only do you not need to, you are not allowed to. The memory used in b is a part of the memory used in a; you need to free the latter as a single unit, and that includes all of the memory for b.
In general, your program should call free exactly once for each call to malloc or calloc. This doesn’t mean the number of lines of code calling free needs to be the same as the number of lines calling allocation functions; it means that each time you run the program, each call to free should be paired with exactly one call to an allocation function, and vice versa, with limited exceptions:
If the allocation fails (and returns NULL), you don’t need to call free on NULL.
You can call free on NULL as many times as you want, although you usually don’t want.
You might call library functions which then allocate or free memory internally. This isn’t really an exception; each of those functions must still be matched with a corresponding free or allocation (respectively), but if you just look at malloc, calloc, and free you might miss something.
When your earliest opportunity to free a chunk of memory is right before the program exits, you don’t need to bother, because the OS reclaims all the memory atthat point anyway. This point in particular has its own caveats, but they are at best tangential to this issue.
If you fail to free memory which was allocated, you have a memory leak. Your program will use more and more memory until the OS can’t give it any more, at which point it will probably crash.
If you free memory which was not allocated by one of the standard allocation functions, or free the same memory twice, it gets even worse: this is immediately undefined behavior (UB) and might do anything*. This is the type of bug you would introduce by trying to free b; the memory in question was not the actual pointer returned by calloc, and even if it were it would have already been freed as part of a.
* People often say UB might do anything a lot, but in practice you can often predict what will happen on a real system; it won’t make your computer explode unless you actually have a USB bomb plugged into the computer in question. However, I would classify invalid frees as one of the less-tame types of UB: the errors it introduces can in practice appear later than the actual bug, cause seemingly unrelated issues, and be unstable between multiple runs of the program (meaning things might look fine when you test but fail when you try to use the program, and be hard to debug). With many other forms of UB this is allowed but not as likely in practice to happen.

In this case, no.
You would only need to manually free the inner struct if it was allocated separately from the outer struct. Example:
struct a_struct
{
struct b_struct *b;
};
int main( void )
{
struct a_struct *a = malloc( sizeof *a );
if ( a ) // *Always* check the result of malloc or calloc
{
a->b = malloc( sizeof *a->b );
if ( a->b )
{
// do stuff with a->b->c
free( a->b ); // free in reverse order that you allocated
}
free( a );
}
return 0;
}
You should only free pointer values returned from malloc, calloc, or realloc.

Related

In C, why are the first members of a struct frequently "reset" to 0 when it is deallocated with free()?

The setup
Let's say I have a struct father which has member variables such as an int, and another struct(so father is a nested struct). This is an example code:
struct mystruct {
int n;
};
struct father {
int test;
struct mystruct M;
struct mystruct N;
};
In the main function, we allocate memory with malloc() to create a new struct of type struct father, then we fill it's member variables and those of it's children:
struct father* F = (struct father*) malloc(sizeof(struct father));
F->test = 42;
F->M.n = 23;
F->N.n = 11;
We then get pointers to those member variables from outside the structs:
int* p = &F->M.n;
int* q = &F->N.n;
After that, we print the values before and after the execution of free(F), then exit:
printf("test: %d, M.n: %d, N.n: %d\n", F->test, *p, *q);
free(F);
printf("test: %d, M.n: %d, N.n: %d\n", F->test, *p, *q);
return 0;
This is a sample output(*):
test: 42, M.n: 23, N.n: 11
test: 0, M.n: 0, N.n: 1025191952
*: Using gcc (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0
Full code on pastebin: https://pastebin.com/khzyNPY1
The question
That was the test program that I used to test how memory is deallocated using free(). My idea(from reading K&R "8.7 Example - A Storage Allocator", in which a version of free() is implemented and explained) is that, when you free() the struct, you're pretty much just telling the operating system or the rest of the program that you won't be using that particular space in memory that was previously allocated with malloc(). So, after freeing those memory blocks, there should be garbage values in the member variables, right? I can see that happening with N.n in the test program, but, as I ran more and more samples, it was clear that in the overwhelming majority of cases, these member variables are "reset" to 0 more than any other "random" value. My question is: why is that? Is it because the stack/heap is filled with zeroes more frequently than any other value?
As a last note, here are a few links to related questions but which do not answer my particular question:
C - freeing structs
What REALLY happens when you don't free after malloc?
After calling free, the pointers F, p and q no longer point to valid memory. Attempting to dereference those pointers invokes undefined behavior. In fact, the values of those pointers become indeterminate after the call to free, so you may also invoke UB just by reading those pointer values.
Because dereferencing those pointers is undefined behavior, the compiler can assume it will never happen and make optimizations based on that assumption.
That being said, there's nothing that states that the malloc/free implementation has to leave values that were stored in freed memory unchanged or set them to specific values. It might write part of its internal bookkeeping state to the memory you just freed, or it might not. You'd have to look at the source for glibc to see exactly what it's doing.
Apart from undefined behavior and whatever else the standard might dictate, since the dynamic allocator is a program, fixed a specific implementation, assuming it does not make decisions based on external factors (which it does not) the behavior is completely deterministic.
Real answer: what you are seeing here is the effect of the internal workings of glibc's allocator (glibc is the default C library on Ubuntu).
The internal structure of an allocated chunk is the following (source):
struct malloc_chunk {
INTERNAL_SIZE_T mchunk_prev_size; /* Size of previous chunk (if free). */
INTERNAL_SIZE_T mchunk_size; /* Size in bytes, including overhead. */
struct malloc_chunk* fd; /* double links -- used only if free. */
struct malloc_chunk* bk;
/* Only used for large blocks: pointer to next larger size. */
struct malloc_chunk* fd_nextsize; /* double links -- used only if free. */
struct malloc_chunk* bk_nextsize;
};
In memory, when the chunk is in use (not free), it looks like this:
chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Size of previous chunk, if unallocated (P clear) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Size of chunk, in bytes |A|M|P| flags
mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| User data starts here... |
Every field except mchunk_prev_size and mchunk_size is only populated if the chunk is free. Those two fields are right before the user usable buffer. User data begins right after mchunk_size (i.e. at the offset of fd), and can be arbitrarily large. The mchunk_prev_size field holds the size of the previous chunk if it's free, while the mchunk_size field holds the real size of the chunk (which is at least 16 bytes more than the requested size).
A more thorough explanation is provided as comments in the library itself here (highly suggested read if you want to know more).
When you free() a chunk, there are a lot of decisions to be made as to where to "store" that chunk for bookkeeping purposes. In general, freed chunks are sorted into double linked lists based on their size, in order to optimize subsequent allocations (that can get already available chunks of the right size from these lists). You can see this as a sort of caching mechanism.
Now, depending on your glibc version, they could be handled slightly differently, and the internal implementation is quite complex, but what is happening in your case is something like this:
struct malloc_chunk *victim = addr; // address passed to free()
// Add chunk at the head of the free list
victim->fd = NULL;
victim->bk = head;
head->fd = victim;
Since your structure is basically equivalent to:
struct x {
int a;
int b;
int c;
}
And since on your machine sizeof(struct malloc_chunk *) == 2 * sizeof(int), the first operation (victim->fd = NULL) is effectively wiping out the contents of the first two fields of your structure (remember, user data begins exactly at fd), while the second one (victim->bk = head) is altering the third value.
The Standard specifies nothing about the behavior of a program that uses a pointer to allocated storage after it has been freed. Implementations are free to extend the language by specifying the behavior of more programs than required by the Standard, and the authors of the Standard intended to encourage variety among implementations which would support popular extensions on a quality-of-implementation basis directed by the marketplace. Some operations with pointers to dead objects are widely supported (e.g. given char *x,*y; the Standard would allow conforming implementations to behave in arbitrary fashion if a program executes free(x); y=x; in cases where x had been non-null, without regard for whether anything ever does anything with y after its initialization, but most implementations would extend the language to guarantee that such code would have no effect if y is never used) but dereferencing of such pointers generally isn't.
Note that if one were to pass two copies of the same pointer to a freed object to:
int test(char *p1, char *p2)
{
char *q;
if (*p1)
{
q = malloc(0):
free(q);
return *p1+*p2;
}
else
return 0;
}
it is entirely possible that the act of allocating and freeing q would disturb the bit patterns in the storage that had been allocated to *p1 (and also *p2), but a compiler would not be required to allow for that possibility. A compiler might plausibly return the sum of the value that was read from *p1 before the malloc/free, and a value that was read from *p2 after it; this sum could be an odd number even though if p1 and p2 are equal, *p1+*p2 should always be even.
Two things happen when you call free:
In the C model of computing, any pointer values that point to the freed memory (either its beginning, such as your F, or things within it, such as your p and q) are no longer valid. The C standard does not define what happens when you attempt to use these pointer values, and optimization by the compiler may have unexpected effects on how your program behaves if you attempt to use them.
The freed memory is released for other purposes. One of the most common other purposes for which it is used is tracking memory that is available for allocation. In other words, the software that implements malloc and free needs data structures to record which blocks of memory have been freed and other information. When you free memory, that software often uses some of the memory for this purpose. That can result in the changes you saw.
The freed memory may also be used by other things in your program. In a single-threaded program without signal handlers or similar things, generally no software would run between the free and the preparation of the arguments to the printf you show, so nothing else would reuse the memory so quickly—reuse by the malloc software is the most likely explanation for what you observed. However, in a multithreaded program, the memory might be reused immediately by another thread. (In practice, this may be a bit unlikely, as the malloc software may keep preferentially separate pools of memory for separate threads, to reduce the amount of inter-thread synchronization that is necessary.)
When a dynamically allocated object is freed, it no longer exists. Any subsequent attempt to access it has undefined behavior. The question is therefore nonsense: the members of an allocated struct cease to exist at the end of the host struct's lifetime, so they cannot be set or reset to anything at that point. There is no valid way to attempt to determine any values for such no-longer-existing objects.

Repeatedly allocate memory without freeing it

The following code shows an example that repeatedly allocates memory without first calling free. Instead, it frees **sign after the loop.
#include <stdio.h>
#include <stdlib.h>
float ** fun(int nloc)
{
float **sign;
int i,nt=100,it,k;
sign=(float **)calloc(nloc,sizeof(float *));
for (i=0;i<nloc;i++)
sign[i] = (float *)calloc(nt,sizeof(float *));
for (it=0;it<nt;it++){
for (k=0;k<nloc;k++){
sign[k][it]=it*0.2;
}
}
return sign;
}
int main(int argc, char *argv[])
{
int i,isrc,n=3,nloc=1;
float **sign=NULL;
for (isrc=0;isrc<n;isrc++){
sign = fun(nloc);
}
for (i=0;i<nloc;i++){
free(sign[i]);
}
free(sign);
exit(0);
}
This is a correct code snippet. My question is: why is it legal that we can allocate memory for a pointer in each iteration without having to free it first?
[Supplementary message]:
Hi all, I think there's one case we cannot free memory in the loop. If buffer=p and p is defined outside the loop, like:
float *buffer, *p;
/* Elements of p calculated */
for (...){
/* allocate memory for **buffer */
buffer = p;
free(buffer)
/* if free here will cause p lost */
}
If free buffer at the end of each loop, it may cause p lost because buffer and p share the same memory address.
why is it legal that we can allocate memory for a pointer in each iteration without having to free it first?
The responsibility of freeing dynamically allocated memory is left on the programmer. It is legal because the compiler does not enforce it, although there are code checking tools that can flag this problem.
Freeing dynamically allocated memory should be done in the reverse order of allocation. For ex:
for (i=0;i<nloc;i++)
free(sign[i]);
free(sign);
It is legal because in C, you as the programmer are responsible for memory management. There is a very good reason for this. To quote another thread
Garbage collection requires data structures for tracking allocations
and/or reference counting. These create overhead in memory,
performance, and the complexity of the language. C++ is designed to be
"close to the metal", in other words, it takes the higher performance
side of the tradeoff vs convenience features. Other languages make
that tradeoff differently. This is one of the considerations in
choosing a language, which emphasis you prefer.
Not only is performance and code size a consideration, but different systems have difference addressing schemes for memory. It is also for this reason that C is easy to port and maintain across platforms, given that there is no garbage collection to alter.
EDIT: Some answers mention freeing memory space as opposed to the pointer itself, it is worth further specifying what that means: free() simply marks the allocated space as available, it is not 'freed' or erased, nor does any other operation occur on that memory space. It is then still incumbent on the programmer to delete the address that was assigned to the pointer variable.
My question is: why is it legal that we can allocate memory for a pointer in each iteration without having to free it first?
Short answer
C trades away safety to gain simplicity and performance.
Longer answer
You don't free the pointer. You free the memory block the pointer is pointing at.
Think about what malloc (and calloc) does. They both allocate a piece of memory, and if the allocation is successful they return a pointer to that memory block. The allocation functions (like all functions) has no insight, nor control whatsoever of what you do with the return value. The functions does not even see the pointer that you are assigning the return value to.
It would be fairly complex (relatively speaking, C has a pretty simple structure) to implement a protection against it. First, consider this code:
int * a = malloc(1);
int * b = a;
a = malloc(1);
free(b);
free(a);
This code has no memory leaks, even though we did the precise thing you asked about. We reassigned a before calling free upon the memory from the first malloc. It works fine, because we have saved the address in b.
So in order to disallow reassigning pointers that points to a memory block that no other pointer points at, the runtime environment would need to keep track of this, and it is not entirely trivial. And it would also need to create extra code to handle all this. Since this check needs to be done at runtime, it may affect performance.
Also, remember that even though C may seem very low level today, it was considered a high level language when it came.

Freeing dynamically allocated int that needs to be returned but cannot be freed in main in c

As my long title says: I am trying to return a pointer in c that has been dynamically allocated, I know, I have to free it, but I do not know how to myself, my search has showed that it can only be freed in main, but I cannot leave it up to the user to free the int.
My code looks like this right now,
int *toInt(BigInt *p)
{
int *integer = NULL;
integer = calloc(1, sizeof(int));
// do some stuff here to make integer become an int from a passed
// struct array of integers
return integer;
}
I've tried just making a temp variable and seeing the integer to that then freeing integer and returning the temp, but that hasn't worked. There must be a way to do this without freeing in main?
Program design-wise, you should always let the "module" (translation unit) that did the allocation be responsible for freeing the memory. Expecting some other module or the caller to free() memory is indeed bad design.
Unfortunately C does not have constructors/destructors (nor "RAII"), so this has to be handled with a separate function call. Conceptually you should design the program like this:
#include "my_type.h"
int main()
{
my_type* mt = my_type_alloc();
...
my_type_free(mt);
}
As for your specific case, there is no need for dynamic allocation. Simply leave allocation to the caller instead, and use a dedicated error type for reporting errors:
err_t toInt (const BigInt* p, int* integer)
{
if(bad_things())
return ERROR;
*integer = p->stuff();
return OK;
}
Where err_t is some custom error-handling type (likely enum).
Your particular code gains nothing useful from dynamic allocation, as #unwind already observed. You can save yourself considerable trouble by just avoiding it.
In a more general sense, you should imagine that with each block of allocated memory is associated an implicit obligation to free. There is no physical or electronic representation of that obligation, but you can imagine it as a virtual chit associated at any given time with at most one copy of the pointer to the space during the lifetime of the allocation. You can transfer the obligation between copies of the pointer value at will. If the pointer value with the obligation is ever lost through going out of scope or being modified then you have a leak, at least in principle; if you free the space via a copy of the pointer that does not at that time hold the obligation to free, then you have a (possibly virtual) double free.
I know I have to free it, but I do not know how to myself
A function that allocates memory and returns a copy of the pointer to it without making any other copies, such as your example, should be assumed to associate the obligation to free with the returned pointer value. It cannot free the allocated space itself, because that space must remain allocated after the function returns (else the returned pointer is worse than useless). If the obligation to free were not transferred to the returned pointer then a (virtual) memory leak would occur when the function's local variables go out of scope at its end, leaving no extant copy of the pointer having obligation to free.
I cannot leave it up to the user to free the int.
If you mean you cannot leave it up to the caller, then you are mistaken. Of course you can leave it up to the caller. If in fact the function allocates space and returns a pointer to it as you describe, then it must transfer the obligation to free to the caller along with the returned copy of the pointer to the allocated space. That's exactly what the calloc() function does in the first place. Other functions do similar, such as POSIX's strdup().
Because there is no physical or electronic representation of obligation to free, it is essential that your functions document any such obligations placed on the caller.
Just stop treating it as a pointer, there's no need for a single int.
Return it directly, and there will be no memory management issues since it's automatically allocated:
int toInt(const BigInt *p)
{
int x;
x = do some stuff;
return x;
}
The caller can just do
const int my_x = toInt(myBigInt);
and my_x will be automatically cleaned away when it does out of scope.

Return a pointer to a dynamically-allocated struct vs. requiring allocated memory from the calling function?

In C, it is possible for functions to return pointers to memory that that function dynamically-allocated and require the calling code to free it. It's also common to require that the calling code supplies a buffer to a second function, which then sets the contents of that buffer. For example:
struct mystruct {
int a;
char *b;
};
struct mystruct *get_a_struct(int a, char*b)
{
struct mystruct *m = malloc(sizeof(struct mystruct));
m->a = a;
m->b = b;
return m;
}
int init_a_struct(int a, char*b, struct mystruct *s)
{
int success = 0;
if (a < 10) {
success = 1;
s->a = a;
s->b = b;
}
return success;
}
Is one or the other method preferable? I can think of arguments for both: for the get_a_struct method the calling code is simplified because it only needs to free() the returned struct; for the init_a_struct method there is a very low likelihood that the calling code will fail to free() dynamically-allocated memory since the calling code itself probably allocated it.
It depends on the specific situation but in general supplying the allocated buffer seems to be preferable.
As mentioned by Jim, DLLs can cause problems if called function allocates memory. That would be the case if you decide to distribute the code as a Dll and get_a_struct is exported to/is visible by the users of the DLL. Then the users have to figure out, hopefully from documentation, if they should free the memory using free, delete or other OS specific function. Furthermore, even if they use the correct function to free the memory they might be using a different version of the C/C++ runtime. This can lead to bugs that are rather hard to find. Check this Raymond Chen post or search for "memory allocation dll boundaries". The typical solution is export from the DLL your own free function. So you will have the pair: get_a_struct/release_a_struct.
In the other hand, sometimes only the called function knows the amount of memory that needs to be allocated. In this case it makes more sense for the called function to do the allocation. If that is not possible, say because of the DLL boundary issue, a typical albeit ugly solution is to provide a mechanism to find this information. For example in Windows the GetCurrentDirectory function will return the required buffer size if you pass 0 and NULL as its parameters.
I think that providing the already allocated struct as an argument is preferable, because in most cases you wouldn't need to call malloc/calloc in the calling code, and therefore worrying about free'ing it. Example:
int init_struct(struct some_struct *ss, args...)
{
// init ss
}
int main()
{
struct some_struct foo;
init_struct(&foo, some_args...);
// free is not needed
}
The "pass an pointer in is preferred", unless it's absolutely required that every object is a "new object allocated from the heap" for some logistical reason - e.g. it's going to be put into a linked list as a node, and the linked-list handler will eventually destroy the elements by calling free - or some other situation where "all things created from here will go to free later on).
Note that "not calling malloc" is always the preferred solution if possible. Not only does calling malloc take some time, it also means that some place, you will have to call free on the allocated memory, and every allocated object takes several bytes (typically 12-40 bytes) of "overhead" - so allocating space for small objects is definitely wasteful.
I agree with other answers that passing the allocated struct is preferred, but there is one situation where returning a pointer may be preferred.
In case you need to explicitly free some resource at the end (close a file or socket, or free some memory internal to the struct, or join a thread, or something else that would require a destructor in C++), I think it may be better to allocate internally, then returning the pointer.
I think it so because, in C, it means some kind of a contract: if you allocate your own struct, you shouldn't have to do anything to destroy it, and it be automatically cleared at the end of the function. On the other hand, if you received some dynamically allocated pointer, you feel compelled to call something to destroy it at the end, and this destroy_a_struct function is where you will put the other cleanup tasks needed, alongside free.

Malloc in C why to use it

I am new at C language and I need to create a queue and I don´t if I need to use a malloc (memory allocation) and how to use it. I had run add, remove, size and isempty without malloc and it worked.
void e1_init(e1queue_t* q){
q->head = 0;
q->tail = sizeof(q->queue)/sizeof(int)-1;
q->size=0;
}
Thanks.
In C, there are two kinds of memory:
The Stack
The Heap
Stack memory is rather limited and is used for automatic variables in functions, processing overhead, things like that.
When you need a larger chunk of memory, you need to get it from the heap.
Not an exact duplicate of this answer, but this seems to be a good description:
What and where are the stack and heap?
C dynamic memory allocation refers to performing dynamic memory allocation in the C programming language via a group of functions in the C standard library, namely malloc, realloc, calloc and free
Syntax:
#include <stdlib.h>
Description:
The function malloc() returns a pointer to a chunk of memory of size size, or NULL if there is an error. The memory pointed to will be on the heap, not the stack, so make sure to free it when you are done with it.
Example:
typedef struct data_type {
int age;
char name[20];
} data;
data *bob;
bob = (data*) malloc( sizeof(data) );
if( bob != NULL ) {
bob->age = 22;
strcpy( bob->name, "Robert" );
printf( "%s is %d years old\n", bob->name, bob->age );
}
free( bob );
Good Read C dynamic memory allocation
There are many reasons to use malloc() function.
malloc() is used to dynamically allocate memory for variables.
why?
There can be many reasons to allocate memory dynamically. For instance if the size of a certain object/variable isn't known at COMPILE time, and there might be a reason to increase it later on, then its required to increase the memory requirement. and this is where malloc comes in.
malloc() is used to initialize POINTERS
why?
POINTERS that aren't initialized point to a random location. This location may be in-accessible and might crash the program. When malloc is used, it increases the heap storage and points the randomly initialized pointer to a "sane" location, which can be read/written to.
also, pointers initialized with malloc can be resized using realloc() method. This makes memory management flexible(and error prone as well)

Resources