Search code examples
cstm32heap-corruption

Log an array of bytes without fragmenting heap


I am running some code on a STM32 chip which is logging to my uart port.

I am having a hard time finding the proper way to log an array of bytes. I wrote this function:

static void LogBytes(uint8_t *data, uint32_t length)
{
    char message[length*6]={};
    static char byteRepresentation[6];

    for (uint32_t i=0; i<length; i++)
    {
        sprintf(byteRepresentation, "0x%02X ", data[i] & 0xFF);
        strncat(message, byteRepresentation, 6);
    }

    logger.WriteDebug(LoggingCategorySio, message);
}

But when I run this, I eventually get hard faults (which are a pain to troubleshoot, but I suspect it's caused by heap corruption/fragementation).

I think the problem is caused by strncat (the comment to this answer warns about some problems I might be experiencing). I also read to stay away from malloc / free as much as possible. So I am trying to do as much as I can on the stack.

Am I missing some stupid bug in this code? Or should it be done completely different?

From the comment:

"there are other, quicker and more efficient alternatives (such as strcpy() or memmove()) that could be used instead. Pretty much whatever the question of 'what should I use', strncat() is not the answer"

Is it indeed better to use strcpy / memmove? Or do they in fact rely more on malloc / free and thus should I avoid that even more?


Solution

  • If the problem did end up being from heap overuse (from strncat), then you could try out this implementation that uses the return from sprintf to append to the string as your building it.

    static void LogBytes(uint8_t *data, uint32_t length)
    {
        char message[length*6];
        memset(message, 0, length*6);
        size_t message_offset = 0;
    
        for (uint32_t i=0; i<length; i++)
        {   
            int ret = sprintf(message + message_offset, "0x%02X ", data[i] & 0xFF);
            if (ret > 0){
                message_offset += ret;
            } else {
                //TODO react however you want to sprintf error
                break;
            }   
        }   
    
        logger.WriteDebug(LoggingCategorySio, message);
    }
    
    

    However, there could also be problems from overflowing the stack. If that's the problem, then this variable length array char message[length*6]; might be the culprit for hardfaulting when printing super large arrays.