Search code examples
structmallockeilcircular-buffer

malloc - Hardfault - Keil uVision


I am using 72kB Flash with 16kB RAM Controller. IDE : Keil uVision v5.29 IDE.

I'm creating a circular buffer, which is a pointer to structure.

The malloc is creating a hardfault. the code:

/*** Header File *****/


typedef struct circular_structbuf_t circular_structbuf_t;

typedef circular_structbuf_t* scbuf_handle_t;

/****** C file *****/
struct main_struct
{
    int data;
    char char_data;
}

struct circular_structbuf_t
{
    struct  main_struct st_array[128];
    uint8_t st_head;
    uint8_t st_tail;
    uint8_t st_max; //of the buffer
    bool st_full;
};


scbuf_handle_t circular_structbuf_init(scbuf_handle_t scbuf, size_t size)
{
    scbuf = malloc(sizeof(circular_structbuf_t));                       // Causes Hardfault
    scbuf->st_max = size;
    circular_structbuf_reset(scbuf);
    return scbuf;
}


/** Main File ***/
scbuf_handle_t p_cbuf;


int main(void)
{
    p_cbuf=circular_structbuf_init(p_cbuf,50);
    
}

While debugging, the address to p_cbuf is assigned as 0x0.


Solution

  • Your target system has very little RAM. It is possible that malloc() is unable to meet the allocation request, but you do not test for malloc() failure. The hard fault may be caused by your dereferencing a null pointer at scbuf->st_max = size;.

    Try reducing the structure size, with a lower number of entries in st_array, check if malloc() returns NULL and signal this error using whatever means of communication you have. You might also need to adjust the stack size and the heap size.

    Note also these remarks:

    • if circular_structbuf_init always allocates a new structure, it should not take scbuf as an argument.
    • you could reduce the memory footprint of this structure using a flexible array: the st_array is moved at the end of the structure and only enough space for the head and the actual number of elements is allocated.

    Here is a modified version:

    /*** Header File *****/
    
    typedef struct circular_structbuf_t circular_structbuf_t;
    
    typedef circular_structbuf_t *scbuf_handle_t;
    
    /****** C file *****/
    
    struct main_struct {
        int data;
        char char_data;  // if `int` is aligned, there will be some padding after this field
    };
    
    struct circular_structbuf_t {
        uint8_t st_head;
        uint8_t st_tail;
        uint8_t st_max; // of the buffer
        bool st_full;   // type bool is assumed to be a `uint8_t`
        struct main_struct st_array[];  // flexible array syntax
    };
    
    scbuf_handle_t circular_structbuf_init(size_t size) {
        scbuf_handle_t scbuf; 
        scbuf = malloc(sizeof(circular_structbuf_t) + size * sizeof(struct main_struct));
        if (scbuf) {
            scbuf->st_max = size;       
            circular_structbuf_reset(scbuf);
        }
        return scbuf;
    }
    
    /** Main File ***/
    
    scbuf_handle_t p_cbuf;
    
    int main(void) {
        p_cbuf = circular_structbuf_init(50);
        if (p_cbuf == NULL) {
            /* report the error */
        }
        ...
        return 0;
    }
    

    If your compiler does not support flexible arrays, you can define st_array as

    struct main_struct st_array[0];
    

    If this alternative is also rejected by the compiler, use 1 for the defined size.