Archive for April, 2009

C: Mitigating Memory Management Mistakes

So your C code has invalid allocations, double frees, pointer arithmetic errors and generally crashes. That’s ok.

First of all, check the return value of every malloc/calloc/realloc.


#include <assert.h>
void myfunction(int n) {
int * arr = (int*) malloc(n, sizeof(int));
/* assert(arr != NULL); -- for development */
if(arr == NULL) {
perror("memory could not be allocated");
// error handling
}
...

Your code will crash sooner or later, but if you handle it now, you will know why.

Valgrind:

You will not be able to get everything right, except with excessive effort. Try valgrind, it prints out what memory you illegally accessed, left unfreed (leaks), etc.. Best of all: It tells you where exactly in your code.

Example output.

==19182== Invalid write of size 4
==19182==    at 0x804838F: f (example.c:6)
==19182==    by 0x80483AB: main (example.c:11)
==19182==  Address 0x1BA45050 is 0 bytes after a block of size 40 alloc'd
==19182==    at 0x1B8FF5CD: malloc (vg_replace_malloc.c:130)
==19182==    by 0x8048385: f (example.c:5)
==19182==    by 0x80483AB: main (example.c:11)

call it like this:

$ valgrind --leak-check=full ./myprog.exe

DUMA:

Beside having a silly acronym (Detect Unintended Memory Access), this library protects you from illegal memory access. The previous name is more accurate: “ElectricFence”. Usually the OS is very lenient about memory access (no checks make stuff fast), except when you run into other programs space. To make the usual output (“Segmentation fault.”) more colorful, and to terminate early (so that your debug output matches the access), run your (or any) program with

$ LD_PRELOAD=libduma.so.0.0.0 ./myprog.exe

The LD_PRELOAD is a bash feature (read about it elsewhere), it saves you from linking your program with the library.
Last word I wanted to say: With DUMA or valgrind, your program will run slower (all allocated memory is registered). Be a good programmer and make your programs pointer perfect (what’s up with the alliterations by the way), so that the OS doesn’t have to do it.

No Comments

Java concepts in C: garbage collection

While purists will say using a garbage collector in C is blasphemy, it has been shown that very often code runs faster when a garbage collector is in use.
Also, sometimes it occurs that you have to leave a function due to a error case and don’t want to copy all the cleanup to every exit point. You should if you can.

When you have memory leaks, and don’t use a garbage collector, your program will also become slower and slower.

However, luckily good garbage collectors exist and are easy to use. E.g. the good old boehm gc. Linux distributors usually provide a package.

You can include my memory.h and just call mem_malloc, mem_calloc, mem_realloc, mem_free instead of without the mem. for people that don’t have boehmgc installed, you still remain compatible. Of course there are other ways too.


#ifndef MEMORY_H_
#define MEMORY_H_
#include "debug.h"
#define FREEMSG(x) IFSEGV dump_p("about to free", (void*)x);
#ifdef WITHOUT_GARBAGE_COLLECTOR
#define mem_malloc(x) malloc(x)
#define mem_calloc(n,x) calloc(n, x)
#define mem_realloc(p,x) realloc(p,x)
#define mem_free(x) { FREEMSG(x); free(x); (x) = NULL; }
#else
#include <gc.h>
#define mem_malloc(x) GC_malloc(x)
#define mem_calloc(n,x) GC_malloc((n)*(x))
#define mem_realloc(p,x) GC_realloc((p),(x))
#define mem_free(x) { FREEMSG(x); (x) = NULL; }
#endif
#endif /* MEMORY_H_ */

No Comments