记录一个没有碎片堆的字节数组

Log an array of bytes without fragmenting heap

我正在 运行正在记录到我的 uart 端口的 STM32 芯片上的一些代码。

我很难找到记录字节数组的正确方法。我写了这个函数:

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);
}

但是当我 运行 这样做时,我最终会遇到硬故障(很难排除故障,但我怀疑它是由堆 corruption/fragementation 引起的)。

我认为问题是由 strncat 引起的(对 this answer 的评论警告我可能遇到的一些问题)。我还读到尽可能远离 malloc / free。所以我正在努力在堆栈上做尽可能多的事情。

我是否遗漏了这段代码中的一些愚蠢的错误?还是应该完全不同?

来自评论:

"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"

使用strcpy / memmove 确实更好吗?还是他们实际上更多地依赖 malloc / free,因此我应该避免更多?

如果问题最终是由堆过度使用引起的(来自 strncat),那么您可以尝试使用 sprintf 中的 return 附加到字符串的实现作为你的建筑。

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);
}

但是,堆栈溢出也可能会出现问题。如果这是问题所在,那么这个可变长度数组 char message[length*6]; 可能是打印超大数组时出现硬故障的罪魁祸首。