I've always heard that in C you have to really watch how you manage memory. And I'm still beginning to learn C, but thus far, I have not had to do any memory managing related activities at all.. I always imagined having to release variables and do all sorts of ugly things. But this doesn't seem to be the case.
Can someone show me (with code examples) an example of when you would have to do some "memory management" ?
There are two places where variables can be put in memory. When you create a variable like this:
int a;
char c;
char d[16];
The variables are created in the "stack". Stack variables are automatically freed when they go out of scope (that is, when the code can't reach them anymore). You might hear them called "automatic" variables, but that has fallen out of fashion.
Many beginner examples will use only stack variables.
The stack is nice because it's automatic, but it also has two drawbacks: (1) The compiler needs to know in advance how big the variables are, and (2) the stack space is somewhat limited. For example: in Windows, under default settings for the Microsoft linker, the stack is set to 1 MB, and not all of it is available for your variables.
If you don't know at compile time how big your array is, or if you need a big array or struct, you need "plan B".
Plan B is called the "heap". You can usually create variables as big as the Operating System will let you, but you have to do it yourself. Earlier postings showed you one way you can do it, although there are other ways:
int size;
// ...
// Set size to some value, based on information available at run-time. Then:
// ...
char *p = (char *)malloc(size);
(Note that variables in the heap are not manipulated directly, but via pointers)
Once you create a heap variable, the problem is that the compiler can't tell when you're done with it, so you lose the automatic releasing. That's where the "manual releasing" you were referring to comes in. Your code is now responsible to decide when the variable is not needed anymore, and release it so the memory can be taken for other purposes. For the case above, with:
free(p);
What makes this second option "nasty business" is that it's not always easy to know when the variable is not needed anymore. Forgetting to release a variable when you don't need it will cause your program to consume more memory that it needs to. This situation is called a "leak". The "leaked" memory cannot be used for anything until your program ends and the OS recovers all of its resources. Even nastier problems are possible if you release a heap variable by mistake before you are actually done with it.
In C and C++, you are responsible to clean up your heap variables like shown above. However, there are languages and environments such as Java and .NET languages like C# that use a different approach, where the heap gets cleaned up on its own. This second method, called "garbage collection", is much easier on the developer but you pay a penalty in overhead and performance. It's a balance.
(I have glossed over many details to give a simpler, but hopefully more leveled answer)
Here's an example. Suppose you have a strdup() function that duplicates a string:
char *strdup(char *src)
{
char * dest;
dest = malloc(strlen(src) + 1);
if (dest == NULL)
abort();
strcpy(dest, src);
return dest;
}
And you call it like this:
main()
{
char *s;
s = strdup("hello");
printf("%s\n", s);
s = strdup("world");
printf("%s\n", s);
}
You can see that the program works, but you have allocated memory (via malloc) without freeing it up. You have lost your pointer to the first memory block when you called strdup the second time.
This is no big deal for this small amount of memory, but consider the case:
for (i = 0; i < 1000000000; ++i) /* billion times */
s = strdup("hello world"); /* 11 bytes */
You have now used up 11 gig of memory (possibly more, depending on your memory manager) and if you have not crashed your process is probably running pretty slowly.
To fix, you need to call free() for everything that is obtained with malloc() after you finish using it:
s = strdup("hello");
free(s); /* now not leaking memory! */
s = strdup("world");
...
Hope this example helps!
You have to do "memory management" when you want to use memory on the heap rather than the stack. If you don't know how large to make an array until runtime, then you have to use the heap. For example, you might want to store something in a string, but don't know how large its contents will be until the program is run. In that case you'd write something like this:
char *string = malloc(stringlength); // stringlength is the number of bytes to allocate
// Do something with the string...
free(string); // Free the allocated memory
I think the most concise way to answer the question in to consider the role of the pointer in C. The pointer is a lightweight yet powerful mechanism that gives you immense freedom at the cost of immense capacity to shoot yourself in the foot.
In C the responsibility of ensuring your pointers point to memory you own is yours and yours alone. This requires an organized and disciplined approach, unless you forsake pointers, which makes it hard to write effective C.
The posted answers to date concentrate on automatic (stack) and heap variable allocations. Using stack allocation does make for automatically managed and convenient memory, but in some circumstances (large buffers, recursive algorithms) it can lead to the horrendous problem of stack overflow. Knowing exactly how much memory you can allocate on the stack is very dependent on the system. In some embedded scenarios a few dozen bytes might be your limit, in some desktop scenarios you can safely use megabytes.
Heap allocation is less inherent to the language. It is basically a set of library calls that grants you ownership of a block of memory of given size until you are ready to return ('free') it. It sounds simple, but is associated with untold programmer grief. The problems are simple (freeing the same memory twice, or not at all [memory leaks], not allocating enough memory [buffer overflow], etc) but difficult to avoid and debug. A hightly disciplined approach is absolutely mandatory in practive but of course the language doesn't actually mandate it.
I'd like to mention another type of memory allocation that's been ignored by other posts. It's possible to statically allocate variables by declaring them outside any function. I think in general this type of allocation gets a bad rap because it's used by global variables. However there's nothing that says the only way to use memory allocated this way is as an undisciplined global variable in a mess of spaghetti code. The static allocation method can be used simply to avoid some of the pitfalls of the heap and automatic allocation methods. Some C programmers are surprised to learn that large and sophisticated C embedded and games programs have been constructed with no use of heap allocation at all.
There are some great answers here about how to allocate and free memory, and in my opinion the more challenging side of using C is ensuring that the only memory you use is memory you've allocated - if this isn't done correctly what you end up with is the cousin of this site - a buffer overflow - and you may be overwriting memory that's being used by another application, with very unpredictable results.
An example:
int main() {
char* myString = (char*)malloc(5*sizeof(char));
myString = "abcd";
}
At this point you've allocated 5 bytes for myString and filled it with "abcd\0" (strings end in a null - \0).
If your string allocation was
myString = "abcde";
You would be assigning "abcde" in the 5 bytes you've had allocated to your program, and the trailing null character would be put at the end of this - a part of memory that hasn't been allocated for your use and could be free, but could equally be being used by another application - This is the critical part of memory management, where a mistake will have unpredictable (and sometimes unrepeatable) consequences.
A thing to remember is to always initialize your pointers to NULL, since an uninitialized pointer may contain a pseudorandom valid memory address which can make pointer errors go ahead silently. By enforcing a pointer to be initialized with NULL, you can always catch if you are using this pointer without initializing it. The reason is that operating systems "wire" the virtual address 0x00000000 to general protection exceptions to trap null pointer usage.
Also you might want to use dynamic memory allocation when you need to define a huge array, say int[10000]. You can't just put it in stack because then, hm... you'll get a stack overflow.
Another good example would be an implementation of a data structure, say linked list or binary tree. I don't have a sample code to paste here but you can google it easily.
(I'm writing because I feel the answers so far aren't quite on the mark.)
The reason you have to memory management worth mentioning is when you have a problem / solution that requires you to create complex structures. (If your programs crash if you allocate to much space on the stack at once, that's a bug.) Typically, the first data structure you'll need to learn is some kind of list. Here's a single linked one, off the top of my head:
typedef struct listelem { struct listelem *next; void *data;} listelem;
listelem * create(void * data)
{
listelem *p = calloc(1, sizeof(listelem));
if(p) p->data = data;
return p;
}
listelem * delete(listelem * p)
{
listelem next = p->next;
free(p);
return next;
}
void deleteall(listelem * p)
{
while(p) p = delete(p);
}
void foreach(listelem * p, void (*fun)(void *data) )
{
for( ; p != NULL; p = p->next) fun(p->data);
}
listelem * merge(listelem *p, listelem *q)
{
while(p != NULL && p->next != NULL) p = p->next;
if(p) {
p->next = q;
return p;
} else
return q;
}
Naturally, you'd like a few other functions, but basically, this is what you need memory management for. I should point out that there are a number tricks that are possible with "manual" memory management, e.g.,
Using the fact that malloc is guaranteed (by the language standard) to return a pointer divisible by 4,
allocating extra space for some sinister purpose of your own,
creating memory pools..
Get a good debugger... Good luck!
#Euro Micelli
One negative to add is that pointers to the stack are no longer valid when the function returns, so you cannot return a pointer to a stack variable from a function. This is a common error and a major reason why you can't get by with just stack variables. If your function needs to return a pointer, then you have to malloc and deal with memory management.
#Ted Percival:
...you don't need to cast malloc()'s return value.
You are correct, of course. I believe that has always been true, although I don't have a copy of K&R to check.
I don't like a lot of the implicit conversions in C, so I tend to use casts to make "magic" more visible. Sometimes it helps readability, sometimes it doesn't, and sometimes it causes a silent bug to be caught by the compiler. Still, I don't have a strong opinion about this, one way or another.
This is especially likely if your compiler understands C++-style comments.
Yeah... you caught me there. I spend a lot more time in C++ than C. Thanks for noticing that.
In C, you actually have two different choices. One, you can let the system manage the memory for you. Alternatively, you can do that by yourself. Generally, you would want to stick to the former as long as possible. However, auto-managed memory in C is extremely limited and you will need to manually manage the memory in many cases, such as:
a. You want the variable to outlive the functions, and you don't want to have global variable. ex:
struct pair{
int val;
struct pair *next;
}
struct pair* new_pair(int val){
struct pair* np = malloc(sizeof(struct pair));
np->val = val;
np->next = NULL;
return np;
}
b. you want to have dynamically allocated memory. Most common example is array without fixed length:
int *my_special_array;
my_special_array = malloc(sizeof(int) * number_of_element);
for(i=0; i
c. You want to do something REALLY dirty. For example, I would want a struct to represent many kind of data and I don't like union (union looks soooo messy):
struct data{
int data_type;
long data_in_mem;
};
struct animal{/*something*/};
struct person{/*some other thing*/};
struct animal* read_animal();
struct person* read_person();
/*In main*/
struct data sample;
sampe.data_type = input_type;
switch(input_type){
case DATA_PERSON:
sample.data_in_mem = read_person();
break;
case DATA_ANIMAL:
sample.data_in_mem = read_animal();
default:
printf("Oh hoh! I warn you, that again and I will seg fault your OS");
}
See, a long value is enough to hold ANYTHING. Just remember to free it, or you WILL regret. This is among my favorite tricks to have fun in C :D.
However, generally, you would want to stay away from your favorite tricks (T___T). You WILL break your OS, sooner or later, if you use them too often. As long as you don't use *alloc and free, it is safe to say that you are still virgin, and that the code still looks nice.
Sure. If you create an object that exists outside of the scope you use it in. Here is a contrived example (bear in mind my syntax will be off; my C is rusty, but this example will still illustrate the concept):
class MyClass
{
SomeOtherClass *myObject;
public MyClass()
{
//The object is created when the class is constructed
myObject = (SomeOtherClass*)malloc(sizeof(myObject));
}
public ~MyClass()
{
//The class is destructed
//If you don't free the object here, you leak memory
free(myObject);
}
public void SomeMemberFunction()
{
//Some use of the object
myObject->SomeOperation();
}
};
In this example, I'm using an object of type SomeOtherClass during the lifetime of MyClass. The SomeOtherClass object is used in several functions, so I've dynamically allocated the memory: the SomeOtherClass object is created when MyClass is created, used several times over the life of the object, and then freed once MyClass is freed.
Obviously if this were real code, there would be no reason (aside from possibly stack memory consumption) to create myObject in this way, but this type of object creation/destruction becomes useful when you have a lot of objects, and want to finely control when they are created and destroyed (so that your application doesn't suck up 1GB of RAM for its entire lifetime, for example), and in a Windowed environment, this is pretty much mandatory, as objects that you create (buttons, say), need to exist well outside of any particular function's (or even class') scope.
Related
I have been reading that malloc is used for dynamic memory allocation. But if the following code works...
int main(void) {
int i, n;
printf("Enter the number of integers: ");
scanf("%d", &n);
// Dynamic allocation of memory?
int int_arr[n];
// Testing
for (int i = 0; i < n; i++) {
int_arr[i] = i * 10;
}
for (int i = 0; i < n; i++) {
printf("%d ", int_arr[i]);
}
printf("\n");
}
... what is the point of malloc? Isn't the code above just a simpler-to-read way to allocate memory dynamically?
I read on another Stack Overflow answer that if some sort of flag is set to "pedantic", then the code above would produce a compile error. But that doesn't really explain why malloc might be a better solution for dynamic memory allocation.
Look up the concepts for stack and heap; there's a lot of subtleties around the different types of memory. Local variables inside a function live in the stack and only exist within the function.
In your example, int_array only exists while execution of the function it is defined in has not ended, you couldn't pass it around between functions. You couldn't return int_array and expect it to work.
malloc() is used when you want to create a chunk of memory which exists on the heap. malloc returns a pointer to this memory. This pointer can be passed around as a variable (eg returned) from functions and can be used anywhere in your program to access your allocated chunk of memory until you free() it.
Example:
'''C
int main(int argc, char **argv){
int length = 10;
int *built_array = make_array(length); //malloc memory and pass heap pointer
int *array = make_array_wrong(length); //will not work. Array in function was in stack and no longer exists when function has returned.
built_array[3] = 5; //ok
array[3] = 5; //bad
free(built_array)
return 0;
}
int *make_array(int length){
int *my_pointer = malloc( length * sizeof int);
//do some error checking for real implementation
return my_pointer;
}
int *make_array_wrong(int length){
int array[length];
return array;
}
'''
Note:
There are plenty of ways to avoid having to use malloc at all, by pre-allocating sufficient memory in the callers, etc. This is recommended for embedded and safety critical programs where you want to be sure you'll never run out of memory.
Just because something looks prettier does not make it a better choice.
VLAs have a long list of problems, not the least of which they are not a sufficient replacement for heap-allocated memory.
The primary -- and most significant -- reason is that VLAs are not persistent dynamic data. That is, once your function terminates, the data is reclaimed (it exists on the stack, of all places!), meaning any other code still hanging on to it are SOL.
Your example code doesn't run into this problem because you aren't using it outside of the local context. Go ahead and try to use a VLA to build a binary tree, then add a node, then create a new tree and try to print them both.
The next issue is that the stack is not an appropriate place to allocate large amounts of dynamic data -- it is for function frames, which have a limited space to begin with. The global memory pool, OTOH, is specifically designed and optimized for this kind of usage.
It is good to ask questions and try to understand things. Just be careful that you don't believe yourself smarter than the many, many people who took what now is nearly 80 years of experience to design and implement systems that quite literally run the known universe. Such an obvious flaw would have been immediately recognized long, long ago and removed before either of us were born.
VLAs have their place, but it is, alas, small.
Declaring local variables takes the memory from the stack. This has two ramifications.
That memory is destroyed once the function returns.
Stack memory is limited, and is used for all local variables, as well as function return addresses. If you allocate large amounts of memory, you'll run into problems. Only use it for small amounts of memory.
When you have the following in your function code:
int int_arr[n];
It means you allocated space on the function stack, once the function will return this stack will cease to exist.
Image a use case where you need to return a data structure to a caller, for example:
Car* create_car(string model, string make)
{
Car* new_car = malloc(sizeof(*car));
...
return new_car;
}
Now, once the function will finish you will still have your car object, because it was allocated on the heap.
The memory allocated by int int_arr[n] is reserved only until execution of the routine ends (when it returns or is otherwise terminated, as by setjmp). That means you cannot allocate things in one order and free them in another. You cannot allocate a temporary work buffer, use it while computing some data, then allocate another buffer for the results, and free the temporary work buffer. To free the work buffer, you have to return from the function, and then the result buffer will be freed to.
With automatic allocations, you cannot read from a file, allocate records for each of the things read from the file, and then delete some of the records out of order. You simply have no dynamic control over the memory allocated; automatic allocations are forced into a strictly last-in first-out (LIFO) order.
You cannot write subroutines that allocate memory, initialize it and/or do other computations, and return the allocated memory to their callers.
(Some people may also point out that the stack memory commonly used for automatic objects is commonly limited to 1-8 mebibytes while the memory used for dynamic allocation is generally much larger. However, this is an artifact of settings selected for common use and can be changed; it is not inherent to the nature of automatic versus dynamic allocation.)
If the allocated memory is small and used only inside the function, malloc is indeed unnecessary.
If the memory amount is extremely large (usually MB or more), the above example may cause stack overflow.
If the memory is still used after the function returned, you need malloc or global variable (static allocation).
Note that the dynamic allocation through local variables as above may not be supported in some compiler.
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.
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.
I am sure someone must have implemented something like this already!
What I am looking for is the ability to "checkpoint" the heap state and then clear all allocations that have happened since the last checkpoint.
Basically what I am looking for is a natural corollary of the _CrtMemCheck Apis.
Something like(preferably cross-platform)
//we save the heap state here in s1
_CrtMemCheckpoint( &s1 );
//allocs and frees
//Get rid of all allocs since checkpoint s1 that have not been freed!
_CrtMemClearAllObjectsSince(&s1);
There is no standard way to use mark/release memory allocation in C. If you know for a fact that all malloc/free calls will be used in a LIFO fashion, you may be able to link in your ownmalloc/free` functions using something like the following:
#define MY_HEAP_SIZE 12345678
unsigned char my_mem[MY_HEAP_SIZE];
unsigned char *my_alloc_ptr = my_mem;
void *malloc(size_t size)
{
void *ret = my_alloc_ptr;
if (size <= MY_HEAP_SIZE && ((my_alloc_ptr - my_mem)+size) <= MY_HEAP_SIZE)
{
my_alloc_ptr += size;
return (void*)ret;
}
else
return (void*)0;
}
void free(void *ptr)
{
if (ptr)
my_alloc_ptr = ptr;
}
This approach requires zero bytes of overhead per allocation block, but calling free() on any block will also free all blocks that were allocated later. An alternative approach which could be used if the external code doesn't use malloc/free in LIFO order, but it would be okay if blocks don't freed until your code does so, would be to make free() do nothing, but have some other function which behaves like free above. More sophisticated variations are possible as well, but in cases where the first approach will suffice, there's no beating its efficiency. Very nice for embedded systems (though I'd usually call it something other than malloc).
You can modify malloc()/free() using hooks to remember allocated memory (for example, suppose that your record the new pointer in an array of pointers). Then your can have two functions:
int get_checkpoint(), that returns the next free array index,
void free_until(int checkpoint), that frees memory from the current stored pointer in the array backwards, until checkpoint is reached.
This way, you can do:
int cpoint = get_checkpoint();
LibraryDoSomething();
free_until(cpoint);
Of course, this technique is still dangerous; calling a C library function can have side effects that you can easily affect. The best advice is still that of Amardeep.
Another possible and interesting solution could be the use of LD_PRELOAD. As the man page for LD_PRELOAD states "This can be used to selectively override functions in other shared libraries."
Thus, you can have your own implementations of malloc and free wherein you can implement the required checks and then call the default malloc or free.
You can check the details here: http://somethingswhichidintknow.blogspot.com/2009/10/dll-injection.html
I am new in C, trying to figure out about memory allocation in C that I kinda confused
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
int a;
} struct1_t;
int main()
{
funct1(); //init pointer
return 1;
}
int funct2(struct1_t *ptr2struct)
{
printf("print a is %d\n",ptr2struct->a);
//free(ptr2struct);
printf("value of ptr in funct2 is %p\n", ptr2struct);
return 1; //success
}
int funct1(){
struct1_t *ptr2struct = NULL;
ptr2struct = malloc(sizeof(*ptr2struct));
ptr2struct->a = 5;
printf("value of ptr before used is %p", ptr2struct);
if (funct2(ptr2struct) == 0) {
goto error;
}
free(ptr2struct);
printf("value of ptr in funct1 after freed is is %p\n", ptr2struct);
return 1;
error:
if(ptr2struct) free(ptr2struct);
return 0;
}
I have funct 1 that calls funct 2, and after using the allocated pointer in funct1, I try to free the pointer. And I create a case where if the return value in funct2 is not 1, then try again to free the pointer.
My question is below
which practice is better, if I should free the memory in funct2 (after I pass it) or in funct1 (after I finish getting the return value of funct1)
The second thing is whether this is correct to make a goto error, and error:
if(ptr2struct) free(ptr2struct);
My third question is , how do I check if the allocated value is already freed or not? because after getting the return value, I free the pointer, but if I print it, it shows the same location with the allocated one (so not a null pointer).
Calling free() on a pointer doesn't change it, only marks memory as free. Your pointer will still point to the same location which will contain the same value, but that value can now get overwritten at any time, so you should never use a pointer after it is freed. To ensure that, it is a good idea to always set the pointer to NULL after free'ing it.
1) Should I free it in the calling function or in the called function?
I try to do the free-ing in the same function that does the malloc-ing. This keeps the memory-management concerns in one place and also gives better separation of concerns, since the called function in this case can also work with pointers that have not been malloc-ed or use the same pointer twice (if you want to do that).
2) Is it correct to do a "goto error"?
Yes! By jumping to a single place at the end of the function you avoid having to duplicate the resource-releasing code. This is a common pattern and isn't that bad since the "goto" is just serving as a kind of "return" statement and isn't doing any of its really tricky and evil stuff it is more known for.
//in the middle of the function, whenever you would have a return statement
// instead do
return_value = something;
goto DONE;
//...
DONE:
//resorce management code all in one spot
free(stuff);
return return_value;
C++, on the other hand, has a neat way to do this kind of resource management. Since destructors are deterministically called right before a function exits they can be used to neatly package this king of resource management. They call this technique RAII
Another way other languages have to deal with this is finally blocks.
3) Can I see if a pointer has already been freed?
Sadly, you can't. What some people do is setting the pointer variable value to NULL after freeing it. It doesn't hurt (since its old value shouldn't be used after being freed anyway) and it has the nice property that freeing a null pointer is specified to be a no-op.
However, doing so is not foolproof. Be careful about having other variables aliasing the same pointer since they will still contain the old value, that is now a dangerous dangling pointer.
My question is below
which practice is better, if I should free the memory in funct2 (after I pass it) or in funct1 (after I finish getting the return value of funct1)
This is an "ownership" question. Who owns the allocated memory. Typically, this has to be decided based on the design of your program. For example, the only purpose of func1() could be to only allocate memory. That is, in your implementation, func1() is the function for memory allocation and then the "calling" function uses the memory. In that case, the ownership to free the memory is with the caller of func1 and NOT with func1().
The second thing is whether this is correct to make a goto error, and error:
The use of "goto" is generally frowned about. It causes mess in the code that could just be easily avoided. However, I say "generally". There are cases where goto can be quiet handy and useful. For example, in big systems, configuration of the system is a big step. Now, imagine you call a single Config() function for the system which allocates memory for its different data structures at different points in the function like
config()
{
...some config code...
if ( a specific feature is enabled)
{
f1 = allocateMemory();
level = 1;
}
....some more code....
if ( another feature is enabled)
{
f2 = allocateMemory();
level = 2;
}
....some more codee....
if ( another feature is enabled)
{
f3 = allocateMemor();
level =3;
}
/*some error happens */
goto level_3;
level_3:
free(f3);
level_2:
free(f2);
level_1:
free(f1);
}
In this case, you can use goto and elegantly free only that much memory that was allocated till the point the configuration failed.
However, suffice to say in your example goto is easily avoidable and should be avoided.
My third question is , how do I check if the allocated value is already freed or not? because after getting the return value, I free the pointer, but if I print it, it shows the same location with the allocated one (so not a null pointer).
Easy. Set the freed memory as NULL. The other advantage, apart from the one mentioned by MK, is that passing NULL pointer to free will cause a NOP i.e. no operation is performed. This will also help you avoid any double delete problems.
What i am about to share are my own development practices in C. They are by NO mean the ONLY way to organize yourself. I am just outlining a way not the way.
Okay, so, in many ways "C" is a loose language, so a lot of discipline and strictness comes from oneself as a developer. I've been developing in "C" for more than 20 years professionally, I've only very rarely have I had to fix any production-grade software that I have developed. While quite a bit of the success may be attributed to experience, a fair chunk of it is rooted in consistent practice.
I follow a set of development practices, which are quite extensive, and deal with everything as trivial as tabs to naming conventions and what not. I will limit my self to what I do about dealing with structures in general and there memory management in particular.
If I have a structure that's used throughout the software, I write create/destroy; init/done type functions for it:
struct foo * init_foo();
void done_foo(struct foo *);
and allocate and de-allocate the structure in these functions.
If I manipulate a structure elements directly all over the program then don't typedef it. I take the pain of using the struct keyword in each declaration so that I know it's a structure. This is sufficient where the pain threshold is NOT so much that I would get annoyed by it. :-)
If I find that the structure is acting VERY much like an object then I choose to manipulate the structure elements STRICTLY through an opaque API; then I define its interface through set/get type functions for each element, I create a 'forward declaration' in the header file used by every other part of the program, create a an opaque typedef to the pointer of the structure, and only declare the actual structure in the structure API implementation file.
foo.h:
struct foo;
typedef struct foo foo_t;
void set_e1(foo_t f, int e1);
int get_ei(foo_t f);
int set_buf(foo_t f, const char *buf);
char * get_buf_byref(foo_t f)
char * get_buf_byval(foo_t f, char *dest, size_t *dlen);
foo.c:
#include <foo.h>
struct foo {
int e1;
char *buf;
...
};
void set_e1(foo_t f, int e1) {
f->e1 = e1;
}
int get_ei(foo_t f) { return f->e1; }
void set_buf(foo_t f, const char *buf) {
if ( f->buf ) free ( f->buf );
f->buf = strdup(buf);
}
char *get_buf_byref(foo_t f) { return f->buf; }
char *get_buf_byval(foo_t f, char **dest, size_t *dlen) {
*dlen = snprintf(*dest, (*dlen) - 1, "%s", f->buf); /* copy at most dlen-1 bytes */
return *dest;
}
If the related structures are very complicated you may even want to implement function pointers right into a base structure and then provide actual manipulators in particular extensions of that structure.
You will see a strong similarity between the approach i've outlined above and object oriented programming. It is meant to be that ...
If you keep your interfaces clean like this, whether or not you have to set instance variables to NULL all over the place won't matter. The code will, hopefully, yield itself to a tighter structure where silly mistakes are less likely.
Hope this helps.
I know this is answered but, I wanted to give my input. As far as I understand, when you call a function with parameters such as here (the pointer), the parameters are pushed to the stack(FILO).
Therefore the pointer passed to the function will be automagically popped off the stack but not freeing the pointer in funct1(). Therefore you would need to free the pointer in funct1() Correct me if I am wrong.