Proper use of malloc [closed]
A chapter out of the book I have been reading has focused on memory management allocating space using malloc linux functions.
Before I read this I would make relatively small programs without allocating space.
Is it acceptable to not do anything in the way of memory allocation for applications whose memory footprint remains under 50MB? What are the repercussions of not doing so?
I think the answers are missing an important point. The size of memory is a relatively specific technical detail which isn't of primary interest. The crucial difference is that between automatic and dynamic storage, and the associated lifetime:
Automatic storage ends at the end of the scope.
Dynamic storage begins with
malloc()
and ends withfree()
, entirely at the discretion (and responsibility) of the user.
If you can and if it makes sense, everything should be automatic. This entails locality and well-defined interfaces. However, in C (not so much in C++) there comes a time when you need to talk about objects that aren't local to the scope. That's when we need dynamic allocation.
The prime example is your typical linked list. The list consists of nodes:
typedef struct node_tmp
{
int data;
struct node_tmp * next;
struct node_tmp * prev;
} node;
Now to talk about such a list boils down to talking about any of its nodes and brachiate along the prev/next pointers. However, the actual nodes cannot sensibly be part of any local scope, so they are usually dynamically allocated:
node * create_list()
{
node * p = malloc(sizeof node); // [1]
p->prev = p->next = 0;
return p;
}
void free_list(node * p) // call with head node
{
while (p->next)
{
node * tmp = p;
p = p->next;
free(tmp); // [2a]
}
free(p); // [2b]
}
void append_to_end(node * p, int data); // etc.
Here the list nodes exist outside any scope, and you have to bring them to life manually using malloc()
, and clean them up when you're done.
You can use linked lists even in the tiniest of programs, but there's no real way around the manual allocation.
Edit: I thought of another example that should really convince you: You might think that you can just make the list with automatically allocated nodes:
node n1, n2, n3; // an automatic linked list
n1.prev = n3.next = 0;
n1.next = &n2; n2.prev = &n1; n2.next = &n3; n3.prev = &n2;
But note that you cannot do this dynamically! "Dynamic" means "at runtime", but automatic variables have to be determined entirely at compile time.
Suppose you wanted a program that reads integers from the user. If it's even, you add it to the list, if it's odd you ignore it, and if it's zero you stop. You cannot possibly realize such a program with automatic allocation, because the allocation needs are only determined at runtime.
It is in such a scenario that you require malloc()
.
If you can do without malloc for small applications, you're probably just not needing to use any heap space. Little utility programs or toy programs often don't. The things you might be doing wrong though to get by when you should be using the heap are:
Arrays. If you find yourself allocating large arrays 'just to make sure everything fits' then you should perhaps be using malloc. At the least, handle the error condition that everything overflows to check they really are big enough. With dynamically allocated arrays, you can make bigger ones on the fly if you find you need more space.
Doing too much recursion. C benefits from flattening out recursion sometimes into loops over arrays, because unlike function languages it can't optimise things properly. If you are getting your storage space by calling function lots to create it, that's pretty dangerous (the program might crash on you one day).
Using static pools of objects (structs, classes). Perhaps you have a ring buffer, and 15 objects that could be in it, and you have them statically allocated because you know that your buffer will never have more than 15 entries. That's kind of OK, but allowing the buffer to grow more by adding in more structs, created with malloc, might be nice.
Probably plenty more situations where programmes which don't need malloc could benefit from having it added.
The size of an application and the use of malloc()
are two independant things. malloc()
is used to allocate memory at runtime, when sizes are not known at compilation time.
Anyway, if you do know the maximum size of the structures that you want to play with, you can statically allocate them and build an application without using malloc()
. Space critical software is an example of such applications.
You were probably allocating memory statically at compile time, but not dynamically.
The possible issue when allocating everything statically are :
- you are wasting memory because you are always allocating an upper limit with a margin.
- in some case, your application will run out of memory (because your estimation was wrong for example), and and since you can not add new memory ressources at runtime it can potentially be lethal.
That being said, in some cases like real-time embedded system, it is a requirement to not allocate any memory dynamically at runtime. (because you have hard memory constraints, or because allocating memory can break real time)
精彩评论