Tell me more ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

Im wondering if there is a set or a few good books/Tutorials/Etc.. that go into Memory Management/Allocation Specifically (or at least have a good dedicated section to it) when it comes to C. This is more for me learning Embedded and trying to keep Size down. I've read and Learned C fine, and the "standard" Learning books.

However most of the books don't spend a huge amount of time (Understandably since C is pretty huge in general) going into the Finer details about whats going on Down Under.

I saw a few on Amazon:

http://www.amazon.com/C-Pointers-Dynamic-Memory-Management/dp/0471561525

http://www.amazon.com/Understanding-Pointers-C-Yashavant-Kanetkar/dp/8176563587/ref=pd_sim_b_1 (Not sure how relevant this would be)

A specific Book for Embedded that has to do with this would be nice. But Code Samples or...Heck tutorials or anything about this topic would be helpful!

share|improve this question
Brace for downvotes... "Resource questions - automatic close?" is on the community bulletin this week. – K.Steff Sep 20 '12 at 1:39
1  
... but resources applicable to specific niches are ruled appropriate. +1. – MSalters Sep 20 '12 at 14:51
Watch for suggestions leading to premature micro-optimization that makes unmaintainable code that is often larger and slower than the simple solution. – mattnz Nov 19 '12 at 1:39

closed as not a real question by maple_shaft Nov 19 '12 at 11:58

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, see the FAQ.

6 Answers

up vote 2 down vote accepted

From my experience, there are a reasonable set of "best practices" that most of the books will cover in greater or lesser detail. To wit,

  • Write the free() immediately after writing the calloc()/malloc() [1]
  • Prefer memmov() to memcpy()
  • Test pointers before using them
  • Track the size of your allocations
  • Use the tracked size of your allocations to test for buffer overruns/underruns. [2]

[1] This usually implies that you are coding from a design, not just hacking it out which is where a lot of allocation bugs seem to originate.

[2] Consider a custom memory structure to act as a "smart" pointer, such as:

#include <stdio.h>
#include <stdlib.h>

struct smart_uint_ptr {
    unsigned long int size;
    unsigned int *data;
};

struct smart_uint_ptr * alloc_smart_uint_ptr(unsigned long int size)
{
    struct smart_uint_ptr *ptr =
        (struct smart_uint_ptr *)calloc(1, sizeof(struct smart_uint_ptr));
    if (ptr != NULL)
    {
        ptr->size = size;
        ptr->data = calloc(size, sizeof(unsigned int));
    }

    return ptr;
}

int main(int argc, char *argv[])
{
    struct smart_uint_ptr * myptr = alloc_smart_uint_ptr(50);

    if (myptr != NULL)
    {
        printf("myptr->size: [%lu]\n", myptr->size);
        free(myptr);
    }
    else
    {
        printf("Could not allocate myptr\n");
    }

    return 0;
}

The custom structure could also house function pointers to alloc/dealloc methods as well as any other sort of "object-like" functionality one may desire.

share|improve this answer
The heap management behind malloc() will already be tracking the size of the allocation, why not use that? – JBRWilkinson Sep 23 '12 at 23:27
@JBR: In standard C, the heap manager has no API to get it. – mattnz Nov 19 '12 at 1:25

This post on Stack Overflow goes into considerable detail as to what to do in order to make programs more compact. It largely seems to depend on byte packing and shaving, the use of bit fields and other manipulations of similar type.

share|improve this answer
Most of the suggestions in that post scream unreliable micro-optimization, for instance bit packing often means bigger code, so what you save in the data page gets consumed in the code page. – mattnz Nov 19 '12 at 1:36

Embedded systems are often very different from each others and the applications can also have different goals that can really change the requirement for a good memory management system. So from my experience (which was mostly consoles) the best practice simply depend of the embedded system and as a result you get the best tips from people who are actually experienced with a particular system.

In my own experience with older consoles, the goal was to simply avoid any dynamic memory allocation since we knew how much memory we had and we could manually map the memory usage. In some cases we needed some dynamic allocation and in this case the best way was to implement your own memory allocator that was optimized for our need.

In fact if you have time, I would recommend writing your own memory allocator even if you don't plan to use it. This is not this complicated and you will really have a better understanding of memory allocation. There is various documentation online like these ones

http://www.ibm.com/developerworks/aix/tutorials/au-memorymanager/au-memorymanager-pdf.pdf http://www.flounder.com/inside_storage_allocation.htm

share|improve this answer

If you are after books, there's Expert C Programming by Peter van der Linden which I can definitely recommend. It's a must read for any serious C programmer. Then of course, there's The C Programming Language by Brian Kernighan and Dennis Ritchie which I assume you have read. If you haven't, then do it now. Really!

share|improve this answer
1  
K&R is terribly outdated, contains far too many errors and teaches bad coding style (or the absence of any coding style at all). I wouldn't recommend it for anything beyond nostalgia. – Lundin Sep 20 '12 at 14:36
1  
Most importantly, it fails to address the specific concerns voiced in the question. – MSalters Sep 20 '12 at 14:52
It is my impression that @Sauron isn't necessarily new to programming and as such a terse, to the point book focusing on content rather than introducing concepts would be ideal. Programming style(and even the lack of it) is more a matter of taste, especially when looking for specific information. Admittedly, there's no escaping the fact that K&R indeed is 1) outdated(and no C99 let alone C11) 2) doesn't cover the exact points, although I firmly believe that it with it's exercises is an awesome resource especially considering it's compactness. If not K&R, then "C Programming: A Modern Approach" – zxcdw Sep 20 '12 at 16:45
Ya Im more looking for specific details on C, not C itself. I do appreciate the suggestions however as some more detailed/indepth C books would be helpful. Speaking of K&R being outdated, are there any "Updated" Books that kinda encompass C as Successfully as K&R did? – Mercfh Sep 20 '12 at 17:21
King's C: A Modern Approach isn't as concise but it is well written, to the point, and thorough. – World Engineer Sep 20 '12 at 17:25

Here is code for a simple suballocator in an OOP-ish version of C that I call Instance Model Programming. The full parser code that this is a part of can be found here. It is quite efficient for allocating large numbers of small variable sized things like strings or structs. The big overhead in malloc/free occurs when lots of freeing is done. This reduces that overhead in the case where fine grained freeing is not needed.

/*************************************************************************

    memory.h

*************************************************************************/

#ifndef _MEMORY_H
#define _MEMORY_H

#define PRIVATE static
#define PUBLIC
#define INSTANCE_METHOD static

// ------------------------------------------------------------------------
// memory_t
// 
// A pseudo-class to avoid global function names and enable initialization.
// reentrant.
// ------------------------------------------------------------------------

#undef  SELF
#define SELF    struct _memory

typedef struct _memory
{
    void  *memory;
    void  *first_chunk;
    int    start;
    int    end;
    int    chunk;

    void * (*allocate) ( SELF *id, int size );
    void * (*save) ( SELF *id, void *, int );
    void   (*release) ( SELF *id );

} memory_t;

#define allocate(self,a)        (*self).allocate(self,a)
#define save(self,a,b)          (*self).save(self,a,b)
#define release(self)           (*self).release(self)

PUBLIC
void
InitializeMemory ( memory_t  *memory );

#endif


/*************************************************************************

    memory.c

*************************************************************************/

#include  
#include 
#include 
#include "memory.h"

// ----------------------------------------------------------------------- 
// set_new_chunk
// 
// allocate another chunk of memory to the struct, zeroed out
// -----------------------------------------------------------------------

PRIVATE
void 
set_new_chunk ( memory_t *d )
{
    void  **next, 
          **last = d->memory;
    int     chunk = d->chunk; 
    size_t  size = sizeof ( double );

    next = calloc ( (chunk / size), size );             // double boundary
    if ( ! next ) {
        puts ("memory_t: out of memory");
        exit(1);
    }
    d->start = sizeof ( void * );              // leave room for "next" pointer
    d->memory = next;
    *last = next;                                   // point to this chunk
}

// ----------------------------------------------------------------------- 
// allocate
// 
// return pointer to allocated memory of length size, zeroed out
// -----------------------------------------------------------------------

INSTANCE_METHOD 
void *
(allocate) ( memory_t  *d,
             int        size )
{
    void   *new_item;

    if ( size > d->chunk - sizeof ( void * ) ) {
        printf ( "memory_t: max memory chunk size is %d bytes\n",
                                                d->chunk - sizeof ( void * ) );
        exit(1); 
    }
    if ( d->start + size > d->end ) {
        set_new_chunk ( d );
    }
    new_item = (char *) d->memory + d->start;
    d->start += size;

    return  new_item;
}

// ----------------------------------------------------------------------- 
// save 
// 
// save item of length size in memory, return pointer to it 
// -----------------------------------------------------------------------

INSTANCE_METHOD 
void *
(save) ( memory_t *d,
         void     *item,
         int       size )
{
    void   *new_item;

    if ( size > d->chunk - sizeof ( void * ) ) {
        printf ( "memory_t: max memory chunk size is %d bytes\n",
                                                d->chunk - sizeof ( void * ) );  
        exit(1); 
    }
    if ( d->start + size > d->end ) {
        set_new_chunk ( d );
    }
    new_item = (char *) d->memory + d->start;
    memcpy ( new_item, item, size );
    d->start += size;

    return  new_item;
}

// ----------------------------------------------------------------------- 
// release 
// -----------------------------------------------------------------------

INSTANCE_METHOD 
void
(release) ( memory_t *d )
{
    register
    void  **next = d->first_chunk;
    void   *memory;

    while ( next ) {
        memory = next; 
        next = *next;
        free ( memory );
    } 
}

// -----------------------------------------------------------------------
// InitializeMemory 
// -----------------------------------------------------------------------

PUBLIC
void
InitializeMemory ( register
                   memory_t  *memory )
{
    register
    void   **next;
    size_t   size = sizeof ( double );
    int      chunk = 64 * 1024;

    memory->start = sizeof ( void * );      // next pointer is first bytes 
    memory->chunk = chunk;
    memory->end  = chunk - 1;
    next = calloc ( (chunk / size), size );         // double boundary
    if ( ! next ) {
        puts ("memory_t: no memory available");
        exit(1);
    }
    memory->first_chunk = next; 
    memory->memory = next; 

    memory->allocate = allocate;
    memory->save = save;
    memory->release = release;
}
share|improve this answer
1  
Whoah, exit() on out-of-memory? On an embedded system? You kidding? – JBRWilkinson Sep 23 '12 at 23:29

I have a copy of the book Code Optimization: Effective Memory Usage by Kris Kaspersky (ISBN 1-931769-24-9). It goes into quite a bit of detail beyond just memory management, covering topics such as profiling and testing, cache coherence, and even other topics related to optimization of code execution. It even came with a CD including all the code from the book.

share|improve this answer

Not the answer you're looking for? Browse other questions tagged or ask your own question.