3

I am trying to undestand the C functions malloc and free. I know this has been discussed a lot on StackOverflow. However, I think I kind of know what these functions do by now. I want to know why to use them. Let's take a look at this piece of code:

int n = 10;
char* array;
array = (char*) malloc(n * sizeof(char));
// Check whether memory could be allocated or not...
// Do whatever with array...
free(array);
array = NULL;

I created a pointer of type char which I called array. Then I used malloc to find a chunk of memory that is currently not used and (10 * sizeof(char)) bytes large. That address I casted to type char pointer before assigning it to my previously created char pointer. Now I can work with my char array. When I am done, I'll use free to free that chunk of memory since it's not being used anymore.

I have one question: Why wouldn't I just do char array[10];? Wikipedia has only one small sentence to give to answer that, and that sentence I unfortunately don't understand:

However, the size of the array is fixed at compile time. If one wishes to allocate a similar array dynamically...

The slide from my university is similarily concise:

It is also possible to allocate memory from the heap.

What is the heap? I know a data structure called heap. :)

However, I've someone could explain to me in which case it makes sense to use malloc and free instead of the regular declaration of a variable, that'd be great. :)

typeduke
  • 6,494
  • 6
  • 25
  • 34
  • 1
    possible duplicate of [What and where are the stack and heap?](http://stackoverflow.com/questions/79923/what-and-where-are-the-stack-and-heap) – AShelly Nov 11 '13 at 19:08
  • 1
    Not exactly duplicate, but should help you understand the difference. – AShelly Nov 11 '13 at 19:09
  • 2
    I don't think this is a duplicate. It is very helpful to understand what the heap is, though. Thanks for sharing! – typeduke Nov 11 '13 at 19:13

6 Answers6

4

C provides three different possible "storage durations" for objects:

  • Automatic - local storage that's specific to the invocation of the function it's in. There may be more than one instance of objects created with automatic storage, if a function is called recursively or from multiple threads. Or there may be no instances (if/when the function isn't being called).

  • Static - storage that exists, in exactly one instance, for the entire duration of the running program.

  • Allocated (dynamic) - created by malloc, and persists until free is called to free it or the program terminates. Allocated storage is the only type of storage with which you can create arbitrarily large or arbitrarily many objects which you can keep even when functions return. This is what malloc is useful for.

R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711
1

Regarding your question: Why wouldn't I just do char array[10];?. You can, and most of the time, that will be completely sufficient. However, what if you wanted to do something similar, but much much bigger? Or what if the size of your data needs to change during execution? These are a few of the situations that point to using dynamically allocated memory (calloc() or malloc()).

Understanding a little about how/when the stack and heap are used would be good: When you use malloc() or calloc(), it uses memory from the heap, where automatic/static variables are given memory on the stack, and are freed when you leave the scope of that variable, i.e the function or block it was declared in.

Using malloc and calloc become very useful when the size of the data you need is not known until run-time. When the size is determined, you can easily call one of these to allocate memory onto the heap, then when you are finished, free it with free()

Regarding What is the heap? There is a good discussion on that topic here (slightly different topic, but good discussion)

In response to However, I've someone could explain to me in which case it makes sense to use malloc() and free()...?

In short, If you know what your memory requirements are at build time (before run-time) for a particular variable(s), use static / automatic creation of variables (and corresponding memory usage). If you do not know what size is necessary until run-time, use malloc() or calloc() with a corresponding call to free() (for each use) to create memory. This is of course a rule-of-thumb, and a gross generalization. As you gain experience using memory, you will find scenarios where even when size information is known before run-time, you will choose to dynamically allocate due to some other criteria. (size comes to mind)

Community
  • 1
  • 1
ryyker
  • 22,849
  • 3
  • 43
  • 87
1

First of all there is no need to cast the malloc

array = malloc(n * sizeof(char));   

I have one question: Why wouldn't I just do char array[10];?

What will you do if you don't know how many storage space do you want (Say, if you wanted to have an array of arbitrary size like a stack or linked list for example)?
In this case you have to rely on malloc (in C99 you can use Variable Length Arrays but for small memory size).

The function malloc is used to allocate a certain amount of memory during the execution of a program. The malloc function will request a block of memory from the heap. If the request is granted, the operating system will reserve the requested amount of memory.

When the amount of memory is not needed anymore, you must return it to the operating system by calling the function free.
In simple: you use an array when you know the number of elements the array will need to hold at compile time. you use malloc with pointers when you don't know how many elements the array will need to be at compile time.
For more detail read Heap Management With malloc() and free().

haccks
  • 104,019
  • 25
  • 176
  • 264
  • So what you are saying is that I cannot do `char array[n]` (like I could in Java for example) while I can do `array = malloc(n * sizeof(char));`. If I correctly interpret what you are saying, I have to use `malloc` in case I don't know how much memory I'll need. Maybe because that depends on some user input. – typeduke Nov 11 '13 at 19:25
  • @baerenfaenger: This answer is wrong where it says you have to rely on `malloc` for this; you can define `char array[n];` with `n` being determined at run-time, in C 1999 and later. However, you should do this only for small sizes (because the space provided for this feature is generally not huge), and the array allocated that way cannot be returned from the function in which it is defined because it ceases to exist when the function exits. So, in most substantial uses of dynamic allocation, you will use `malloc` or a related routine. – Eric Postpischil Nov 11 '13 at 19:28
  • @baerenfaenger: If you do `char array[n];` in Java, it might lead to a `malloc()` call inside the Java-engine. Java `free()`s `malloc()`ed stuff automatically when it is not used anymore, and the only guarantee Java provides is that your array will be allocated as long as you use it. If you do it in C however, it is allocated on the stack and is guaranteed to be cleaned up when the function returns. – Atle Nov 11 '13 at 19:31
  • @EricPostpischil; I missed that VLA's in C99. – haccks Nov 11 '13 at 19:35
  • @EricPostpischil: What do you mean with "because the space provided for this feature is generally not huge"? – typeduke Nov 11 '13 at 20:19
  • 1
    @baerenfaenger: Most C implementations use a stack for automatic allocations, and, and on common systems such as OS X or Windows, the stack is typically one to eight mebibytes or so. The stack must suffice for all routines that are called (at the same time, nested). – Eric Postpischil Nov 11 '13 at 20:27
1

Imagine you want to allocate 1,000 arrays.

If you did not have malloc and free... but needed a declaration in your source for each array, then you'd have to make 1,000 declarations. You'd have to give them all names. (array1, array2, ... array1000).

The idea in general of dynamic memory management is to handle items when the quantity of items is not something you can know in advance at the time you are writing your program.

0

If you know in advance that you only require an array of 10 chars, you should just say char array[10]. malloc is useful if you don't know in advance how much storage you need. It is also useful if you need storage that is valid after the current function returns. If you declare array as char array[10], it will be allocated on the stack. This data will not be valid after your function returns. Storage that you obtain from malloc is valid until you call free on it.

Also, there is no need to cast the return value of malloc.

Ben
  • 683
  • 3
  • 5
0

Why to use free after malloc can be understood in the way that it is a good style to free memory as soon as you don't need it. However if you dont free the memory then it would not harm much but only your run time cost will increase.

You may also choose to leave memory unfreed when you exit the program. malloc() uses the heap and the complete heap of a process is freed when the process exits. The only reason why people insist on freeing the memory is to avoid memory leaks.

From here:

Allocation Myth 4: Non-garbage-collected programs should always deallocate all memory they allocate.

The Truth: Omitted deallocations in frequently executed code cause growing leaks. They are rarely acceptable. but Programs that retain most allocated memory until program exit often perform better without any intervening deallocation. Malloc is much easier to implement if there is no free.

In most cases, deallocating memory just before program exit is pointless. The OS will reclaim it anyway. Free will touch and page in the dead objects; the OS won't.

Consequence: Be careful with "leak detectors" that count allocations. Some "leaks" are good!


Also the wiki has a good point in Heap base memory allocation:-

The heap method suffers from a few inherent flaws, stemming entirely from fragmentation. Like any method of memory allocation, the heap will become fragmented; that is, there will be sections of used and unused memory in the allocated space on the heap. A good allocator will attempt to find an unused area of already allocated memory to use before resorting to expanding the heap. The major problem with this method is that the heap has only two significant attributes: base, or the beginning of the heap in virtual memory space; and length, or its size. The heap requires enough system memory to fill its entire length, and its base can never change. Thus, any large areas of unused memory are wasted. The heap can get "stuck" in this position if a small used segment exists at the end of the heap, which could waste any magnitude of address space, from a few megabytes to a few hundred.

Rahul Tripathi
  • 168,305
  • 31
  • 280
  • 331