内存损坏 malloc(): memory corruption (fast)问题分析

程序运行中报malloc: memory corruption fast

  • 问题描述
  • 问题代码
  • 分析过程
  • 附录

问题描述

自己编写的MQTT报文解析程序运行过程中,运行几分钟后,进程报
Error in ‘./test_lora': malloc(): memory corruption (fast): 0x0000007fa4000a90 Aborted
偶尔也会有
Error in ’./test_lora': free(): invalid next size (fast): 0x0000007f74000ab0 Aborted
然后异常退出。刚开始以为malloc后内存没释放导致,认真走查了代码,加打印,没有发现此问题。
在网上搜了下资料
https://www.jianshu.com/p/a849ed11be68
应该是这些问题中的一种,所以围绕程序的malloc加打印进行调试。

问题代码

//主应用程序

#include <string.h>
#include <unistd.h>
#include "powerdevice.h"

void SensorDataCallBack(const char* devicename, SPM_REQ_DATA* packet)
{
    int i = 0;
    SDATA_NODE *ptNode = NULL;
    printf("device=%s\n",devicename);

    printf("Rcv Sensor Data:ID=%02X%02X%02X%02X%02X%02X\n",packet->sensorId[0],packet->sensorId[1],
        packet->sensorId[2],packet->sensorId[3],packet->sensorId[4],packet->sensorId[5]);
    
    printf("Param Cnt=%d,Pkt Type=%d\n",packet->dataLength,packet->packetType);

    for(i = 0;i < packet->dataLength;i++)
    {
        ptNode = &(packet->dataList[i]);
        //printf("index=%d Param ID=%d,Param Len=%d,Param Type=%d\n",i,ptNode->dataId,ptNode->dataLength,ptNode->dataType);
        
        switch(ptNode->dataType)
        {
            case UNSIGNED_INT_8:
                printf("Param ID=%d,Param Value=%d\n",ptNode->dataId,ptNode->dataValue.uint8Value);
                break;
            
            case UNSIGNED_INT_16:
                printf("Param ID=%d,Param Value=%d\n",ptNode->dataId,ptNode->dataValue.uint16Value);
                break;
            
            case UNSIGNED_INT_24:
            case UNSIGNED_INT_32:
                printf("Param ID=%d,Param Value=%d\n",ptNode->dataId,ptNode->dataValue.uint32Value);
                break;
            
            case FLOAT_32:
                printf("Param ID=%d,Param Value=%f\n",ptNode->dataId,ptNode->dataValue.floatValue);
                break;
            
            default:
                break;
        }
    }
    printf("sensor data call back finish\n");
}


int main()
{
    SOPEN_PARAM tOpenParam;
    SDEVICE *ptDevice = NULL;

    memset(&tOpenParam, 0, sizeof(SOPEN_PARAM));
    tOpenParam.deviceName = g_szBroker;
    tOpenParam.timeout = 15;

    ptDevice = openDevice(tOpenParam, SensorDataCallBack);
    if(NULL == ptDevice)
    {
        printf("open device failed\n");
        return -1;
    }

    while(1)
    {
        sleep(30);
    }

    return 0;
}

//openDevice接口所在库部分代码(增加过调试打印)

SDEVICE *openDevice(SOPEN_PARAM openParam,SensorDataCB callBack)
{
    memset(&g_tDeviceMgr,0,sizeof(T_DeviceMgr));

    g_tDeviceMgr.ptCallBack = callBack;
    g_tDeviceMgr.iTimeOut = openParam.timeout;

    if(!ESP_QueueMgrInit(&g_tDeviceMgr.tProcQueueMgr,ESP_QUEUE_MAX_NUM))
    {
        printf("module  init send queue failed.\n");
        return false;
    }

    if(!espMqttClientInit(openParam.deviceName))
    {
        printf("MQTT Client Init Failed.\n");
        return false;
    }
    
    if(!ESP_ThreadCreate(&g_tDeviceMgr.tProcThreadID,0xf0000,espDeviceMsgProcThread,NULL))
    {
        printf("Device Msg Proc Thread create failed.\n");
        return false;
    }

    sem_init(&(g_tDeviceMgr.tCtrlReqWaitSem),0,0);
    printf("open device success.\n");

    return &g_tDevice;
}

static void *espDeviceMsgProcThread(void * arg)
{
    //从接收队列里取数据串口发送给lP模组
    T_QueueMsg tQueueMsg;
    bool bRet = false;
    T_QueueMgr *ptQueueMgr = &(g_tDeviceMgr.tProcQueueMgr);

    printf("device Msg Proc Thread Start.\n");

    while(1)
    {
        sem_wait(&ptQueueMgr->tSem);
        if(g_tDeviceMgr.bExitFlag)
        {
            pthread_exit(NULL);
        }
        
        bRet = ESP_QueueMsgEx(ptQueueMgr,&tQueueMsg);
        if(!bRet)
        {
            continue;
        }

        if(tQueueMsg.bMsgType == MSG_TYPE_MQTT_RCV)
        {
            espDeviceMsgRcvProc(tQueueMsg.szData);
        }
        else if(tQueueMsg.bMsgType == MSG_TYPE_MQTT_SEND)
        {
            espDeviceMsgSendProc(tQueueMsg.szData,tQueueMsg.iDataLen);
        }
        
        if(NULL != tQueueMsg.szData)
        {
            free(tQueueMsg.szData);
            tQueueMsg.szData = NULL;
        }
    }

    printf("device Msg Proc Thread exit.\n");

   return NULL;
}

static bool espDeviceMsgRcvProc(char *szData)
{
    if( NULL == szData )
    {
        printf("Input buffer is invaild.\n");
        return false;
    }

    cJSON *ptRoot  = NULL;
    cJSON *ptNode = NULL;
    UINT32 iDataLen = 0;
    UINT8  *abData = NULL;
    //UINT8 abData[256] = {0};

    // 1解析json字符串
    ptRoot = cJSON_Parse(szData);
    if(NULL == ptRoot)
    {
        printf("can't trans json obj from buffer\n");
        return false;
    }

    do
    {
        ptNode = cJSON_GetObjectItem(ptRoot,"length");
        if((NULL == ptNode)||(0 == ptNode->valueint))
        {
            printf("Can't get data length from json.\n");
            break;
        }
        iDataLen = ptNode->valueint;
        
        ptNode = cJSON_GetObjectItem(ptRoot,"rawdata");
        if((NULL == ptNode)||(NULL == ptNode->valuestring))
        {
            printf("Can't get raw data from json.\n");
            break;
        }
        printf("--1.iDataLen:%lld\n", iDataLen);
        abData = malloc(iDataLen);
        printf("--1.25.\n");
        if(NULL == abData)
        {
            printf("malloc error.\n");
            break;
        }
        printf("--1.5.\n");

        memset(abData, 0, iDataLen);
        printf("--2.\n");

        ESP_Base64Decode(ptNode->valuestring, abData);
        printf("--2.1.\n");

        // 3 解析报文
        espLoraDataDecode(abData, iDataLen);
         printf("--2.25.\n");
        free(abData);
        printf("--2.5.\n");
    }while(0);

    cJSON_Delete(ptRoot);

    return true;
}

bool ESP_Base64Decode(const char *szBase64, UINT8 *abData)
{
    int i = 0;
    int j = 0;
    int k = 0;
    char temp[4] = "";
    int iStrLen = strlen(szBase64);

    for (i = 0; i < iStrLen; i += 4) 
    {
        for (j = 0; j < 64 ; j++) 
        {
            if (*(szBase64 + i) == base64char[j]) 
            {
                temp[0] = j;
            }
        }

        for (j = 0; j < 64 ; j++) 
        {
            if (*(szBase64 + i + 1) == base64char[j]) 
            {
                temp[1] = j;
            }
        }

        for (j = 0; j < 64 ; j++) 
        {
            if (*(szBase64 + i + 2) == base64char[j]) 
            {
                temp[2] = j;
            }
        }

        for (j = 0; j < 64 ; j++) 
        {
            if (*(szBase64 + i + 3) == base64char[j]) 
            {
                temp[3] = j;
            }
        }

        *(abData + k++) = ((temp[0] << 2) & 0xFC) | ((temp[1]>>4) & 0x03);
        //printf("k=%d\n", k);
        if ( *(abData + i + 2)  == '=' )
        {
            break;
        }

        *(abData + k++) = ((temp[1] << 4) & 0xF0) | ((temp[2]>>2) & 0x0F);
        //printf("k=%d\n", k);
        if ( *(abData + i + 3) == '=' )
        {
            break;
        }

        *(abData + k++) = ((temp[2] << 6) & 0xF0) | (temp[3] & 0x3F);
        //printf("k=%d\n", k);
    }
    
    return true;
}

linux上使用 命令aarch64-linux-gnu-gcc -Wall test.c -o test_lora -DLORADATA_V1 ./libloradec.a -lpthread -lm 进行编译后,生成目标文件 test_lora。”./“运行后,打印如下:

root@tf:/home# ./test_lora
–9.
–10. Mqtt Client Connection success. mqtt init success. open device success. device Msg Proc Thread Start. mqtt connect Thread Start.
Mqtt(loraMQTT) Message arrived:topic: /v1/lcm/data/upload.payloadle=77
message->payload:{
“cmdType”: 45062,
“length”: 17,
“rawdata”: “o08IIAehIDFgAQIZYAECkPo=” }
–11.
–12.
–1.iDataLen:17
–1.25.
–1.5.
–2.
–2.1. Rcv Sensor Monitor Data Report idex=0 param id=6156,datalenflag=1 datalen=1 idex=1 param id=6150,datalenflag=1
datalen=1 device=tcp://127.0.0.1:1883 Rcv Sensor Data:ID=A34F082007A1
Param Cnt=2,Pkt Type=0 Param ID=6156,Param Value=2 Param ID=6150,Param
Value=2 sensor data call back finish Call Back Finished Rcv Sensor
Data Decode finished
–2.25.
–2.5. Mqtt(loraMQTT) Message arrived:topic: /v1/lcm/data/upload.payloadle=109 message->payload:{
“cmdType”: 45062,
“length”: 40,
“rawdata”: “C8EIIbGoUCAASF3VQSUAAj4ADADuRWlAYeoEosoAAGXqBAANJSCtCg==” }
–11.
–12.
–1.iDataLen:40
–1.25.
–1.5.
–2.
–2.1. Rcv Sensor Monitor Data Report idex=0 param id=8,datalenflag=0 datalen=4 idex=1 param id=9,datalenflag=1 datalen=2 idex=2 param
id=3,datalenflag=0 datalen=4 idex=3 param id=15000,datalenflag=1
datalen=4 idex=4 param id=15001,datalenflag=1 datalen=4
device=tcp://127.0.0.1:1883 Rcv Sensor Data:ID=0BC10821B1A8 Param
Cnt=5,Pkt Type=0 Param ID=8,Param Value=26.670547 Param ID=9,Param
Value=62 Param ID=3,Param Value=3.644893 Param ID=15000,Param
Value=51874 Param ID=15001,Param Value=539299072 sensor data call back
finish Call Back Finished Rcv Sensor Data Decode finished
–2.25.
–2.5. Mqtt(loraMQTT) Message arrived:topic: /v1/lcm/data/upload.payloadle=97 message->payload:{
“cmdType”: 45062,
“length”: 31,
“rawdata”: “qG4IwAAuQBgg7J7VQR0gAjwAeAAAAEBBdQACZADGFw==” }
–11.
–12.
–1.iDataLen:31
–1.25.
–1.5.
–2.
–2.1. Rcv Sensor Monitor Data Report idex=0 param id=2054,datalenflag=0 datalen=4 idex=1 param id=2055,datalenflag=1
datalen=2 idex=2 param id=30,datalenflag=0 datalen=4 idex=3 param
id=29,datalenflag=1 datalen=2 device=tcp://127.0.0.1:1883 Rcv Sensor
Data:ID=A86E08C0002E Param Cnt=4,Pkt Type=0 Param ID=2054,Param
Value=26.702599 Param ID=2055,Param Value=60 Param ID=30,Param
Value=12.000000 Param ID=29,Param Value=100 sensor data call back
finish Call Back Finished Rcv Sensor Data Decode finished
–2.25.
–2.5. Mqtt(loraMQTT) Message arrived:topic: /v1/lcm/data/upload.payloadle=77 message->payload:{
“cmdType”: 45062,
“length”: 17,
“rawdata”: “o08IIAehIDFgAQIZYAECkPo=” }
–11.
–12.
–1.iDataLen:17
*** Error in `./test_lora’: malloc(): memory corruption (fast): 0x0000007fa4000a90 *** Aborted

分析过程

根据打印发现进程每次异常退出都发生在espDeviceMsgRcvProc接口中为变量*UINT8 abData使用malloc申请内存时。修改局部变量变量空间申请方式为
UINT8 abData[256] = {0};
删除对变量的malloc和free。
//abData = malloc(iDataLen);
//free(abData);
再次编译运行目标文件,发现运行正常。
问题初步解决,但没有查到根因,继续分析,改回对变量abData 进行malloc方式申请内存空间。
检查malloc申请未发现问题,持续纠结,继续加打印。然后怀疑到可能是数组越界的问题导致。
检查变量abData的调用位置。
在base64解码的接口ESP_Base64Decode中增加打印,编译运行。

root@tf:/home# ./test_lora
–9.
–10. Mqtt Client Connection success. mqtt init success. open device success. mqtt connect Thread Start. device Msg Proc Thread Start.
Mqtt(loraMQTT) Message arrived:topic: /v1/lcm/data/upload.payloadle=77
message->payload:{
“cmdType”: 45062,
“length”: 17,
“rawdata”: “o08IIAehIDFgAQIZYAECkPo=” }
–11.
–12.
–1.iDataLen:17
–1.25.
–1.5.
–2. k=1 k=2 k=3 k=4 k=5 k=6 k=7 k=8 k=9 k=10 k=11 k=12 k=13 k=14 k=15 k=16 k=17 k=18
–2.1. Rcv Sensor Monitor Data Report idex=0 param id=6156,datalenflag=1 datalen=1 idex=1 param id=6150,datalenflag=1
datalen=1 device=tcp://127.0.0.1:1883 Rcv Sensor Data:ID=A34F082007A1
Param Cnt=2,Pkt Type=0 Param ID=6156,Param Value=2 Param ID=6150,Param
Value=2 sensor data call back finish Call Back Finished Rcv Sensor
Data Decode finished
–2.25.
–2.5. Mqtt(loraMQTT) Message arrived:topic: /v1/lcm/data/upload.payloadle=89 message->payload:{
“cmdType”: 45062,
“length”: 25,
“rawdata”: “o08IwCOtMA1gAgIAeAAfhlhAdQACPwBVKg==” }
–11.
–12.
–1.iDataLen:25
–1.25.
–1.5.
–2. k=1 k=2 k=3 k=4 k=5 k=6 k=7 k=8 k=9 k=10 k=11 k=12 k=13 k=14 k=15 k=16 k=17 k=18 k=19 k=20 k=21 k=22 k=23 k=24 k=25
k=26 k=27
–2.1. Rcv Sensor Monitor Data Report idex=0 param id=6147,datalenflag=1 datalen=2 idex=1 param id=30,datalenflag=0
datalen=4 idex=2 param id=29,datalenflag=1 datalen=2
device=tcp://127.0.0.1:1883 Rcv Sensor Data:ID=A34F08C023AD Param
Cnt=3,Pkt Type=0 Param ID=6147,Param Value=2 Param ID=30,Param
Value=3.383186 Param ID=29,Param Value=63 sensor data call back finish
Call Back Finished Rcv Sensor Data Decode finished
–2.25.
–2.5. Mqtt(loraMQTT) Message arrived:topic: /v1/lcm/data/upload.payloadle=85 message->payload:{
“cmdType”: 45062,
“length”: 24,
“rawdata”: “qG4IxQBfMClgAQJ4AAAAQEF1AAJkALJI” }
–11.
–12.
–1.iDataLen:24
–1.25.
–1.5.
–2. k=1 k=2 k=3 k=4 k=5 k=6 k=7 k=8 k=9 k=10 k=11 k=12 k=13 k=14 k=15 k=16 k=17 k=18 k=19 k=20 k=21 k=22 k=23 k=24
–2.1. Rcv Sensor Monitor Data Report idex=0 param id=6154,datalenflag=1 datalen=1 idex=1 param id=30,datalenflag=0
datalen=4 idex=2 param id=29,datalenflag=1 datalen=2
device=tcp://127.0.0.1:1883 Rcv Sensor Data:ID=A86E08C5005F Param
Cnt=3,Pkt Type=0 Param ID=6154,Param Value=2 Param ID=30,Param
Value=12.000000 Param ID=29,Param Value=100 sensor data call back
finish Call Back Finished Rcv Sensor Data Decode finished
–2.25.
–2.5. Mqtt(loraMQTT) Message arrived:topic: /v1/lcm/data/upload.payloadle=77 message->payload:{
“cmdType”: 45062,
“length”: 17,
“rawdata”: “o08IIAehIDFgAQIZYAECkPo=” }
–11.
–12.
–1.iDataLen:17
–1.25.
–1.5.
–2. k=1 k=2 k=3 k=4 k=5 k=6 k=7 k=8 k=9 k=10 k=11 k=12 k=13 k=14 k=15 k=16 k=17 k=18
–2.1. Rcv Sensor Monitor Data Report idex=0 param id=6156,datalenflag=1 datalen=1 idex=1 param id=6150,datalenflag=1
datalen=1 device=tcp://127.0.0.1:1883 Rcv Sensor Data:ID=A34F082007A1
Param Cnt=2,Pkt Type=0 Param ID=6156,Param Value=2 Param ID=6150,Param
Value=2 sensor data call back finish Call Back Finished Rcv Sensor
Data Decode finished
–2.25.
–2.5. Mqtt(loraMQTT) Message arrived:topic: /v1/lcm/data/upload.payloadle=109 message->payload:{
“cmdType”: 45062,
“length”: 40,
“rawdata”: “C8EIIbGoUCAAdO/UQSUAAj4ADADuRWlAYeoEp8oAAGXqBAANJSAP7g==” }
–11.
–12.
–1.iDataLen:40
–1.25.
–1.5.
–2. k=1 k=2 k=3 k=4 k=5 k=6 k=7 k=8 k=9 k=10 k=11 k=12 k=13 k=14 k=15 k=16 k=17 k=18 k=19 k=20 k=21 k=22 k=23 k=24 k=25 k=26 k=27 k=28 k=29
k=30 k=31 k=32 k=33 k=34 k=35 k=36 k=37 k=38 k=39 k=40 k=41 k=42
–2.1. Rcv Sensor Monitor Data Report idex=0 param id=8,datalenflag=0 datalen=4 idex=1 param id=9,datalenflag=1 datalen=2 idex=2 param
id=3,datalenflag=0 datalen=4 idex=3 param id=15000,datalenflag=1
datalen=4 idex=4 param id=15001,datalenflag=1 datalen=4
device=tcp://127.0.0.1:1883 Rcv Sensor Data:ID=0BC10821B1A8 Param
Cnt=5,Pkt Type=0 Param ID=8,Param Value=26.616920 Param ID=9,Param
Value=62 Param ID=3,Param Value=3.644893 Param ID=15000,Param
Value=51879 Param ID=15001,Param Value=539299072 sensor data call back
finish Call Back Finished Rcv Sensor Data Decode finished
–2.25.
–2.5. Mqtt(loraMQTT) Message arrived:topic: /v1/lcm/data/upload.payloadle=97 message->payload:{
“cmdType”: 45062,
“length”: 31,
“rawdata”: “qG4IwAAuQBggnGTWQR0gAjsAeAAAAEBBdQACZAAyTw==” }
–11.
–12.
–1.iDataLen:31
–1.25.
–1.5.
–2. k=1 k=2 k=3 k=4 k=5 k=6 k=7 k=8 k=9 k=10 k=11 k=12 k=13 k=14 k=15 k=16 k=17 k=18 k=19 k=20 k=21 k=22 k=23 k=24 k=25 k=26 k=27 k=28 k=29
k=30 k=31 k=32 k=33
–2.1. Rcv Sensor Monitor Data Report idex=0 param id=2054,datalenflag=0 datalen=4 idex=1 param id=2055,datalenflag=1
datalen=2 idex=2 param id=30,datalenflag=0 datalen=4 idex=3 param
id=29,datalenflag=1 datalen=2 device=tcp://127.0.0.1:1883 Rcv Sensor
Data:ID=A86E08C0002E Param Cnt=4,Pkt Type=0 Param ID=2054,Param
Value=26.799126 Param ID=2055,Param Value=59 Param ID=30,Param
Value=12.000000 Param ID=29,Param Value=100 sensor data call back
finish Call Back Finished Rcv Sensor Data Decode finished
–2.25.
–2.5. Mqtt(loraMQTT) Message arrived:topic: /v1/lcm/data/upload.payloadle=77 message->payload:{
“cmdType”: 45062,
“length”: 17,
“rawdata”: “o08IIAehIDFgAQIZYAECkPo=” }
–11.
–12.
–1.iDataLen:17
*** Error in `./test_lora’: malloc(): memory corruption (fast): 0x0000007f8c000a90 *** Aborted

终于发现接口中对abData 进行了越界操作,修改问题代码(块注释内代码未问题代码)

      *(abData + k++) = ((temp[0] << 2) & 0xFC) | ((temp[1]>>4) & 0x03);
      printf("k=%d\n", k);
      /*if ( *(abData + i + 2)  == '=' )*/
      if ( *(szBase64 + i + 2)  == '=' )
      {
          break;
      }

      *(abData + k++) = ((temp[1] << 4) & 0xF0) | ((temp[2]>>2) & 0x0F);
      printf("k=%d\n", k);
      /*if ( *(abData + i + 3) == '=' )*/
      if ( *(szBase64 + i + 3) == '=' )
      {
          break;
      }

      *(abData + k++) = ((temp[2] << 6) & 0xF0) | (temp[3] & 0x3F);
      printf("k=%d\n", k);

编译运行,问题解决。

附录

库文件以及主程序源码
https://download.csdn.net/download/qqq1112345/85722646

你可能感兴趣的:(C语言,c语言)