在 C 中使用执行子字符串的函数时字符串解析失败

String parsing failes when using a function doing substring in C

我在用 C 解析字符串时遇到问题。它最终会导致 HardFault

单片机:LPC1769, OS: FreeRTOS 10, 工具链:IAR

为了测试,如果我一直发送相同的数据帧(您可以在 parseMessage 函数的 message 变量中看到下面的示例), 解析 5-6 次后一切正常,解析工作如我所料,然后当我向函数发送另一个完全相同的字符串时突然陷入 HardFault

我测试了OnlineGDB中的功能。我没有发现任何问题。

虽然结果相同,但我在下面有几个版本略有不同的函数;

char *substr3(char const *input, size_t start, size_t len) { 
    char *ret = malloc(len+1);
    memcpy(ret, input+start, len);
    ret[len]  = '[=10=]';
    return ret;
}

我已经提取了功能部分以便更好地概述: (不用注意stripEOL(message);调用,它只是去掉行尾字符,但是你可以在我的gdbonline分享中看到它)

void parseMessage(char * message){
        //char* message= "7E00002A347C31323030302D3132353330387C33302E30372E323032307C31317C33307C33317C31352D31367C31357C317C57656E67657274880D";
          
        // Parsing the frame
        char* start;
        char* len;
        char* cmd;
        char* data;
        char* chksum;
        char* end;
        
        stripEOL(message);
        unsigned int messagelen = strlen(message);
        
        start = substr3(message, 0, 2);
        len = substr3(message, 2, 4);
        cmd = substr3(message, 6, 2); 
        data = substr3(message, 8, messagelen-8-4);
        chksum = substr3(message, messagelen-4, 2);
        end = substr3(message, messagelen-2, 2); 
}

只有 data 变量的长度不同。

例如数据 --> "347C31323030302D3132353330387C33302E30372E323032307C31317C33307C33317C31352D31367C31357C317C57656E67657274"

HardFault 调试日志:

LR = 0x8667 反汇编

反汇编中的 PC = 0x2dd0

感谢贡献者,是他们引导我为我的实例找到了解决方案。

由于贡献者没有一个完整的解决方案,而我找到了一个可行的解决方案,我最好为将来可能感兴趣的人写作。

由于我是在 FreeRTOS 10 之上开发我的应用程序并使用 C 库中的 malloc,显然它至少没有配合我的实现。在某些资源中提到,您可以在 FreeRTOS 中使用标准 malloc,但由于某些未知原因我无法管理自己。这可能是一个帮助,如果我增加了堆内存,我不知道,但我也没有打算这样做。

我只是放置了两个包装器函数(在公共文件中的某处),甚至没有更改我的 malloc 和 free 调用。;

创建使用 built-in FreeRTOS 堆的 malloc/free 函数非常简单。我们只是包装 pvPortMalloc/pvPortFree 调用:

void* malloc(size_t size)
{
    void* ptr = NULL;

    if(size > 0)
    {
        // We simply wrap the FreeRTOS call into a standard form
        ptr = pvPortMalloc(size);
    } // else NULL if there was an error

    return ptr;
}
void free(void* ptr)
{
    if(ptr)
    {
        // We simply wrap the FreeRTOS call into a standard form
        vPortFree(ptr);
    }
}

请注意:您不能将其用于堆模式 #1,但不能用于其他堆模式(2、3、4 和 5)。 我建议开始使用 portable/MemMang/heap_4.c