views:

219

answers:

6

Using C, is there a safer way to allocate memory than using malloc? For example, is there a C equivalent of a smart pointer, or some handy function that someone has come up with that makes the process of allocation a little cleaner? I mean, sure, it's only one line anyway, but there must be a more concise way to get it done. I suppose the deallocation portion of this question is included in whether there is something similar to a smart pointer in C.

+1  A: 

Why not just use the stack?

leppie
For whatever reason one would ordinarily not use the stack.
Doug Treadwell
Why not? Because the memory won't survive the exit from the function, that's why not :-)
paxdiablo
+1  A: 

If you really feel C's standard memory management is too unsafe, you should avoid it by either switching to a a different programming language that does memory management for you or by using a garbage collector that also does memory management for you, for example Boehm's:

http://www.hpl.hp.com/personal/Hans_Boehm/gc/

Smart pointers help in C++ but still need awareness, i.e. when you build cyclic structures.

Peter G.
Thanks for an interesting link.
Doug Treadwell
+2  A: 

You could write your own garbage collector. If you can't find one or don't have that kind of time, then the answer is no. That's one of the major reasons that people use C++, the automated resource management is win beyond belief compared to malloc/free. If you can afford the performance of a GC, just move to a faster (to develop in) language. The only other solution is to go to C++, which neither requires a garbage collector nor manual memory management.

DeadMG
Do you have any recommendations about going about building a very simple but effective garbage collection system?
Doug Treadwell
RE: My edit in my answer.
DeadMG
Why write your own garbage collector when there are GCs readily available as I indicated in my answer? Writing a garbage collector certainly is non-trivial.
Peter G.
Well, or write C-Front or some other other-language to C translator that handles the memory management in a C++-like way from the programmer's perspective but actually gets compiled as C code.
Doug Treadwell
@Peter G: Because their performance is bad. A language that's designed to be collected like Java or C# will have better GC performance and have it built-in.
DeadMG
+4  A: 

By using malloc and realloc, followed by extensive testing with Valgrind. Using a GC like Boehm's will bite you in the ass later. If you're using C, use C. One lib worth looking into is halloc.

Isaac Hodes
+1 Valgrind is the way to go. Using a gc in C is just so plain wrong :-).
Helper Method
If gc latencies aren't an issue, you shouldn't be using C anyway. +1 for Valgrind.
Nathon
The halloc library looks interesting. It's closer to the kind of thing I had in mind when I asked the question initially.
Doug Treadwell
I like Valgrind, but I question how relevant that link is to C developers considering a garbage collector. Most people are not writing a high-performance, coroutine-based webserver.
Matthew Flaschen
-1 sorry: your warning about GC applies only to a minority of applications. Although I have not used GC much myself, I have used it more often than I've used ucontext.
Edmund
+0: I agree with Edmund. Regardless which memory management you are going to use, for big applications you cannot ignore how it works. The poster on sheddingbikes did ignore it.
Peter G.
+3  A: 

The safest way to allocate memory is to simply learn how it works properly. If you want a safe language, use a safe one. Java has automated garbage collection, for one.

If you want to use C, your best bet is to embrace it in all its glory. You probably will be burnt at some point but, with pain, comes experience.

One thing I've always found useful for students is to think of every allocation as having one peice of extra information, the responsibility. You pass responsibility for a memory block around with the memory itself and whoever is the last man given the responsibility is the one that must free it.

In addition, no two pieces of code can have reponsibility at the same time. In other words, when you pass memory to another party, you are not allowed to touch it until it's given back.

paxdiablo
Well, this is good advice but it doesn't really answer the question. You're basically saying, don't make any effort to write code that allows you to write future code in a safer way. Instead, either use a language that has such features built in, or put the burden on yourself to remember to handle memory safely. I prefer to take as much off myself as possible when writing code so I can concentrate more on the problem to be solved and less on the details of implementation. Abstracting away the details is generally a good thing, don't you think?
Doug Treadwell
Yes, I do think abstracting away details is good. Where I disagree with you is in what level of details should be abstracted. By all means abstract away the complicated stuff like linked lists or other collections and data structures. But the malloc family is a very basic and very easy-to-use core part of C (that may be because I've been cutting C code for over thirty years).
paxdiablo
Abstracting away complexity like memory management is a great idea. This got +1 for suggesting a safe language (like Java).
Nathon
I agree with you paxdiablo that malloc, realloc, and free are easy to use. I guess I am just trying to make them even easier. It's pretty common for me to try to optimize the amount of typing I need to do (time taken away from thinking about the problem being solved) by trying to turn two lines of code into one, or a long one line into a short one line, or a short one line into an easier to remember one line, etc.
Doug Treadwell
+4  A: 

The process of allocation seems enough clear: each malloc-ed block should be free-ed. The simplest next step (before GC) that comes into mind to me is to write a function that "tracks" your allocation, so that at the exit of your code/function you can free everything you need no more in a single function call (and of course another function allows to free single block as usual). This would add a little bit of memory usage, but once implemented properly would make it easier to free blocks allocated one by one in one single shot.

The usage would be something like:

MemPool *pool = mempool_create();

// use
char *t = mempool_alloc(pool, size);
// ...
char *b = mempool_alloc(pool, size2);
// ...
int *c = mempool_alloc(pool, xy * sizeof(int));
// free a single piece for whatever reason...
mempool_free(pool, b);
// ...

// when you finished with this "pool":
mempool_destroy(pool);

This should at least assure that everything allocated "in" the "pool" is free-ed with mempool_destroy, so in the worst usage you could just alloc everything with the "pool" mechanism, and free everything when you don't need it anymore (e.g. at the exit of a function). (Likely "pool" is not an appropriate name)

ShinTakezou
Aha, very nice! This is also close to what I had in mind when I was writing the question. I appreciate the effort you put into the example.
Doug Treadwell