Static allocation of opaque data types

前端 未结 9 1070
天涯浪人
天涯浪人 2020-11-27 13:50

Very often malloc() is absolutely not allowed when programming for embedded systems. Most of the time I\'m pretty able to deal with this, but one thing irritates me: it keep

9条回答
  •  萌比男神i
    2020-11-27 14:29

    One solution if to create a static pool of struct handle_t objects, and provide then as neceessary. There are many ways to achieve that, but a simple illustrative example follows:

    // In file module.c
    struct handle_t 
    {
        int foo;
        void* something;
        int another_implementation_detail;
    
        int in_use ;
    } ;
    
    static struct handle_t handle_pool[MAX_HANDLES] ;
    
    handle_t* create_handle() 
    {
        int h ;
        handle_t* handle = 0 ;
        for( h = 0; handle == 0 && h < MAX_HANDLES; h++ )
        {
            if( handle_pool[h].in_use == 0 )
            {
                handle = &handle_pool[h] ;
            }
        }
    
        // other initialization
        return handle;
    }
    
    void release_handle( handle_t* handle ) 
    {
        handle->in_use = 0 ;
    }
    

    There are faster faster ways of finding an unused handle, you could for example keep a static index that increments each time a handle is allocated and 'wraps-around' when it reaches MAX_HANDLES; this would be faster for the typical situation where several handles are allocated before releasing any one. For a small number of handles however, this brute-force search is probably adequate.

    Of course the handle itself need no longer be a pointer but could be a simple index into the hidden pool. This would enhance data hiding and protection of the pool from external access.

    So the header would have:

    typedef int handle_t ;
    

    and the code would change as follows:

    // In file module.c
    struct handle_s 
    {
        int foo;
        void* something;
        int another_implementation_detail;
    
        int in_use ;
    } ;
    
    static struct handle_s handle_pool[MAX_HANDLES] ;
    
    handle_t create_handle() 
    {
        int h ;
        handle_t handle = -1 ;
        for( h = 0; handle != -1 && h < MAX_HANDLES; h++ )
        {
            if( handle_pool[h].in_use == 0 )
            {
                handle = h ;
            }
        }
    
        // other initialization
        return handle;
    }
    
    void release_handle( handle_t handle ) 
    {
        handle_pool[handle].in_use = 0 ;
    }
    

    Because the handle returned is no longer a pointer to the internal data, and inquisitive or malicious user cannnot gain access to it through the handle.

    Note that you may need to add some thread-safety mechanisms if you are getting handles in multiple threads.

提交回复
热议问题