Thread: Memory handler

  1. #1
    Registered User Dr. Bebop's Avatar
    Join Date
    Sep 2002
    Posts
    96

    Memory handler

    Okay, here's a custom memory handler I wrote for strings so that I won't have to make a bunch of calls to malloc. I probably won't use it, but it's good practice and might come in handy sometime. The reason I thought this was a good idea was for three reasons.

    1. I can get more memory when the program starts, so if I get everything I need and handle it my way then I won't have problems with malloc failing.
    2. Instead of having pointers to memory all over the place, I know exactly where it is because each block is one after another. I think this would be good for debugging.
    3. Since I only call malloc twice when the program starts, I can get better performance by avoiding expensive malloc calls.

    I'm probably an idiot for trying to do this and I know that it's not made very well, but that's why I'm posting it here. Can anyone give me ideas on what to improve, what I'm doing wrong, and if I'm just a complete loser.

    The header file, my_mem_handler.h
    Code:
    #ifndef MY_MEM_HANDLER
    #define MY_MEM_HANDLER
    
    #include <stdio.h>
    #include <stdlib.h>
    
    /* Exit status */
    #define GOOD_EXIT 0
    #define BAD_EXIT  1
    
    /* Error handling */
    #define ERR_NOMEM     0
    #define ERR_FULL_HEAP 1
    
    extern char *err_msg[];
    
    /* Memory handler */
    typedef struct {
            char *memory; /* Memory to be referenced */
            unsigned *block_sizes; /* The size of each block referenced */
            unsigned blocks; /* The number of blocks referenced */
            unsigned N_alloc; /* Amount of referenced memory in bytes */
            unsigned N_free; /* Amount of free memory in bytes */
    } HEAP;
    
    extern HEAP heap;
    
    /* init_heap allocates memory for the heap
    and sets all heap values to their initial settings.
    This indicates that no memory has been referenced.
    It takes the heap size as an argument. */
    int init_heap( unsigned size );
    
    /* free_heap clears all memory allocated to the
    heap. */
    void free_heap( void );
    
    /* alloc_mem references the first available chunk
    of memory of the given size in the heap to mem. It
    takes two arguments, the address of the pointer to
    be given the reference and the desired size. */
    int alloc_mem( char **mem, unsigned size );
    
    /* free_mem returns the chunk of memory referenced
    by mem to the heap and sets mem to null. */
    void free_mem( char **mem );
    
    #endif
    The source file, my_mem_handler.c
    Code:
    #include "my_mem_handler.h"
    
    char *err_msg[] = {
            "Error, couldn't allocate memory",        /* ERR_NOMEM */
            "Error, not enough heap space available", /* ERR_FULL_HEAP */
    };
    
    HEAP heap;
    
    int init_heap( unsigned size )
    {
            /* Reserve space for the heap and set it to 0 */
            heap.memory = calloc( size, sizeof( char ) );
            if( !heap.memory ) {
                    fputs( err_msg[ERR_NOMEM], stderr );
                    return BAD_EXIT;
            }
    
            /* Reserve space for the block sizes and set it to 0 */
            heap.block_sizes = calloc( size, sizeof( int ) );
            if( !heap.block_sizes ) {
                    fputs( err_msg[ERR_NOMEM], stderr );
                    return BAD_EXIT;
            }
    
            heap.blocks = 0;
            heap.N_alloc = 0;
            heap.N_free = size;
    
            return GOOD_EXIT;
    }
    
    void free_heap( void )
    {
            free( heap.block_sizes );
            free( heap.memory );
    }
    
    int alloc_mem( char **mem, unsigned size )
    {
            /* Not enough space on the heap? */
            if( heap.N_free < size ) {
                    fputs( err_msg[ERR_FULL_HEAP], stderr );
                    return BAD_EXIT;
            }
    
            /* Set mem to the first free block and reset the heap sizes */
            *mem = heap.memory + heap.N_alloc;
            heap.block_sizes[heap.blocks++] = size;
            heap.N_alloc += size;
            heap.N_free -= size;
    
            return GOOD_EXIT;
    }
    
    void free_mem( char **mem )
    {
            heap.blocks--;
    
            /* Reset the sizes to remove a block */
            heap.N_alloc -= heap.block_sizes[heap.blocks];
            heap.N_free += heap.block_sizes[heap.blocks];
    
            /* Clear mem */
            *mem = NULL;
    }
    Processing error: Stupidity detected.
    ------------------------------
    Dr. Bebop
    Windows XP Professional Ed.
    Microsoft Visual Studio 6

  2. #2
    Registered User
    Join Date
    Jun 2002
    Posts
    151
    What would be your expected output from this -

    Code:
    int main()
    {
    	char* m1, *m2, *m3,*m4;
    	
    	init_heap(24);
    	
    	alloc_mem(&m1,8);
    	strcpy(m1,"mmmm111");
    	printf("%s",m1);
    
    	alloc_mem(&m2,8);
    	strcpy(m2,"mmmm222");
    
    	alloc_mem(&m3,8);
    	strcpy(m3,"mmmm333");
    
    	free_mem(&m2);
    
    	alloc_mem(&m4,8);
    	strcpy(m4,"mmmm444");
    
    	printf("%s",m3);
    
    	return 0;
    }
    ?

  3. #3
    Registered User moi's Avatar
    Join Date
    Jul 2002
    Posts
    946
    questions:

    why not return pointer to the allocated memory as malloc() does? (makes code using your memory allocator easier to read as everyone is accustomed to the conventions of standard malloc().)

    why char ** and not void **?
    hello, internet!

  4. #4
    End Of Line Hammer's Avatar
    Join Date
    Apr 2002
    Posts
    6,231
    hmmm, yes, you have a bit of a logic problem, as pointed out by Enmeduranki.


    >>why char ** and not void **?
    because...
    >>here's a custom memory handler I wrote for strings
    When all else fails, read the instructions.
    If you're posting code, use code tags: [code] /* insert code here */ [/code]

  5. #5
    Registered User Dr. Bebop's Avatar
    Join Date
    Sep 2002
    Posts
    96
    Enmeduranki:
    I'd expect that you wouldn't get what you wanted, explained below.

    moi:
    I thought about it, but picked the one I thought would be easier to write without terrible bugs.

    Hammer:
    It's not a logic problem, that's part of the design. You have to call each free in the opposite order that it was allocated, like a stack. I couldn't figure out any good way to use a dynamic array for the heap and still allow freeing the references in random order. The biggest problem would be fragmentation, which I could fix by shuffling the elements of the array, but then I would screw up the current references. So it was easier to do it the way I did.
    Processing error: Stupidity detected.
    ------------------------------
    Dr. Bebop
    Windows XP Professional Ed.
    Microsoft Visual Studio 6

  6. #6
    End Of Line Hammer's Avatar
    Join Date
    Apr 2002
    Posts
    6,231
    >It's not a logic problem, that's part of the design.
    Sounds just like "it's not a bug, it's a feature" ! (j/k)
    When all else fails, read the instructions.
    If you're posting code, use code tags: [code] /* insert code here */ [/code]

  7. #7
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    Hammer, you can really be funny sometimes

    bebop: It looks like you put some thought into it, but you should extend it to work for all types of data. You can alloc it as a char* and cast it to any type. Not trying to be critical though. Job well done I use one all the time, by the way. It handles blocking and non-blocking defragmentation, maintains data structures to hold info on each allocated chunk, and even lets me simulate an OS with it's derived class. MM processes are very interesting stuff to me. Look at a similar post I made on this topic, too, it may be interesting...
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  8. #8
    Registered User Dr. Bebop's Avatar
    Join Date
    Sep 2002
    Posts
    96
    Hammer:
    I'll be sure to change it if you can suggest a way to deal with the problems that would be safer than just trusting the user to not be stupid and call free_mem in the right order.

    Sebastiani:
    I'm not quite good enough to do all of that just yet. And there's really no point in doing it for all kinds of data because the only time I really use malloc is for strings. How would you suggest I go about making one more like yours?
    Processing error: Stupidity detected.
    ------------------------------
    Dr. Bebop
    Windows XP Professional Ed.
    Microsoft Visual Studio 6

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. available memory from task manager
    By George2 in forum Tech Board
    Replies: 10
    Last Post: 01-18-2008, 02:32 AM
  2. Replies: 4
    Last Post: 01-13-2008, 02:14 AM
  3. Question regarding Memory Leak
    By clegs in forum C++ Programming
    Replies: 29
    Last Post: 12-07-2007, 01:57 AM
  4. Memory problem with Borland C 3.1
    By AZ1699 in forum C Programming
    Replies: 16
    Last Post: 11-16-2007, 11:22 AM
  5. Shared Memory - shmget questions
    By hendler in forum C Programming
    Replies: 1
    Last Post: 11-29-2005, 02:15 AM