在函数内部错误定位后,从函数中释放返回的指针会导致芯片崩溃

Freeing returned pointer from function after it is malloc'd inside that function causes chip to crash

本文关键字:函数 指针 崩溃 芯片 返回 定位 错误 内部 释放      更新时间:2023-10-16

我在main

内有此调用
char* IDQueueString = getIDQueue();
pc.printf("[%9.6f] IDQueue: %srn", t.read(), IDQueueString);
free(IDQueueString);

和getidqueue((;是

char* getIDQueue(void)
{
    char* returnString;
    char idString[6];
    uint8_t pointer = 0;
    uint8_t queueLength = 0;
    returnString = (char*)malloc((uint32_t)(sizeof(char*)*128));
    if(returnString != 0){
        pc.printf("[%9.6f] MALLOC: %p, len: %d | LINE %drn", t.read(), returnString, (int)(sizeof(char*)*128), __LINE__);
        for(uint8_t i = 0; i < ID_QUEUE_LENGTH; i ++){
            if(ReceivedIDs[i].id != -1){
                queueLength++;
                sprintf(idString, "%d", (int)ReceivedIDs[i].id);
                for(uint8_t j = 0; j < strlen(idString); j++){
                    returnString[pointer] = idString[j];
                    pointer++;
                }
                returnString[pointer++] = ',';
                returnString[pointer++] = ' ';
            }
        }
        if(queueLength > 0){
            returnString[pointer-2] = '.';
            returnString[pointer-1] = '';
        }
        if(queueLength == 0){
            returnString = (char*)"Empty!";
        }
        return returnString;
    }else{
        free(returnString);
        error("x1b[31mMALLOC %d!x1b[0mrn", __LINE__);
        return (char*)"MALLOC!";
    }
}

当它到达二进制中的free(IDQueueString);时,它将在指令链的某个地方进行:

0x08009d6c:   ldr     r6, [r1, #8]  // *0x2000a208, *0x20008500
0x08009d6e:   ldr     r0, [r2, #4]  // *0x200080d8, *0x1002db40
0x08009d70:   cmp     r2, r6        // *0x1002db40, *0x2000a208

,但它挂在0x08009d6e(或者返回到使用

上循环的WIRQ环路
0x08004ffc:   b.n     0x8004ffc

我想知道是什么原因导致它这样做?显然,free();引起了问题,但我无法弄清楚是什么问题。r1r2的值是0x00000000r00x00000009r60x5DECC885

地址0x20000001-0x2001BFFF (112KB)是SRAM1的范围,0x2001C000-0x2001FFFF (16KB)是SRAM2的范围。

我不知道该值0x5DECC885是什么是关于的,但这可能与USB-OCD接口有关。

我假设我免费使用的方式是不正确的,但是由于我将指针返回到malloc();,为什么我不能以尝试的方式释放返回的指针?

您无法释放任何来自malloc的事物 - 这样做是"未定义的行为",因此取决于您的运行时的设计方式,实际上发生的是"任何事物"有可能的",它可能会悬挂,崩溃,通过向特朗普签署的普京发出粗鲁的信息或"很好"来开始核战争。

有两种针对您的特定情况的解决方案:

如果malloc失败,请返回NULL(如果我们在C 中,则可以选择nullptr(。如果队列为空,请返回包含字符串"空!"字符串的malloc'D字符串。(通过使用strcpy分配或类似(。

另外,只有当您知道队列不包含诸如"Empty!""MALLOC!"之类的单词时,这才有效:在调用free之前,请检查是否不是这些字符串之一(使用if(strcmp("Emtpy!", ...) != 0 && strcmp("MALLOC!", ...) != 0) free(...);

通过将这些字符串在已知字符串的列表中放入,只需返回该条目,就可以更轻松地使您具有通过比较指针值本身来检查"是已知常数字符串"的函数。[实际上,当您正在处理的内容中存在相同的内容字符串时,这也将起作用,因为内容字符串来自您的代码,它将具有不同的地址] - 它也将有助于避免"哦,哦,我更改了返回的字符串的值,但没有在免费之前进行支票,因为它只是bot用途更改的一个地方。

每当我看到灾难性清单时,我都知道这会很愚蠢。错误的程序逻辑 - 但是编译器必须是错误的:(

是分配函数调用之前的内存。所有当地的杂物都应在返回前释放。它使调试代码更容易(尤其是内存泄漏(。

您有数十亿个与程序交流的方式,但是您选择的方法是最糟糕的方法。首先,将错误(例如失败的mallocs(与应用程序异常(如空名称中的空名(分开是一件好事。我本人会使此函数返回int(例如,负面的int作为系统错误,如果可以的话,则为零,而对于应用程序异常,则可以更轻松地处理它们,并且可以通过指针返回指针。但是,您想在功能中进行malloc(并且不自由( -

if((resultCode = getIDQueue(& IDQueueString) >= 0)
{
   // do something (you can have another switch here to deal with application exceptions like empty name for example)
   free(IDQueueString);
}
else
{
 switch (resultCode) 
 {
   case -1:
     // do something malloc failed
     break:
   case -2:
     //deal with another error 
     break;
  //...... etc etc 
   default:
     // ----
     break;
 }
}