This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

MSP430G2755 IAR malloc申请内存地址出现非法

如题,在使用malloc申请内存是地址会出现非法地址,程序处理完后有做free释放。堆栈设置

调试如图

  • 奇怪的问题。方便把代码上传一下吗?

  • 您在编译的时候是没有错误的?

    PS:好久没有用IAR了,现在一直用CCS
  • 您好,感谢回复。

    测试发现使用malloc free就会出现非法地址, 如果使用固定数组申请则正常。请帮忙分析,TSK。

    功能实现:IO口模拟SMBUS  功能code如下:

    swi2c.c-->

    #include "swi2c.h"
    #include "check.h"
    #include <stdlib.h>
    #include <string.h>

    #define buff_size (64)

    void SWI2CMST_init(void)
    {
    PxOUT &= ~(SCL | SDA); // Output settings always LOW
    PxSEL &= ~(SCL | SDA); // Set GPIO functions
    }

    static void delay_us(uint16_t t)
    {
    while(t--);
    }

    static bool SCL_Timeout(void)
    {
    uint16_t ucErrTime=0;
    while(SCL_READ == 0)
    {
    if(ucErrTime++>=10000)//10ms
    return false;
    }
    return true;
    }
    static bool SDA_Timeout(void)
    {
    uint16_t ucErrTime=0;
    while(SDA_READ != 0)
    {
    if(ucErrTime++>=1000)//1ms
    return false;
    }
    return true;
    }

    void SWI2CMST_start(void)
    {
    SDA_1; // SDA = 1
    //delay_us(I2CDELAYUSEC); // Quick delay
    SCL_1; // SCL = 1
    delay_us(I2CDELAYUSEC); // Quick delay
    SDA_0; // SDA = 0
    delay_us(I2CDELAYUSEC); // Quick delay
    SCL_0; // SCL = 0
    delay_us(I2CDELAYUSEC); // Quick delay
    }

    static void SWI2CMST_stop(void)
    {
    SDA_0; // SDA = 0
    delay_us(I2CDELAYUSEC); // Quick delay
    SCL_1; // SCL = 1
    SCL_Timeout();
    delay_us(I2CDELAYUSEC); // Quick delay
    SDA_1; // SDA = 1
    delay_us(I2CDELAYUSEC); // Quick delay
    }
    //成功返回0,失败返回1
    static bool SWI2CMST_txByte(uint8_t data)
    {
    uint8_t bits, temp;
    bool ack;

    SCL_0; // SCL = 0
    temp = data; // Initialize temp variable
    bits = 0x08; // Load I2C bit counter
    while (bits > 0) // Loop until all bits are shifted
    {
    if (temp & BIT7) // Test data bit
    SDA_1; // SDA = 1
    else
    SDA_0; // SDA = 0
    delay_us(I2CDELAYUSEC); // Quick delay
    SCL_1; // SCL = 1
    SCL_Timeout();
    delay_us(I2CDELAYUSEC); // Quick delay
    temp <<= 1; // Shift bits 1 place to the left
    SCL_0; // SCL = 0
    bits--; // Loop until 8 bits are sent
    }
    delay_us(I2CDELAYUSEC);
    //SDA_1; // SDA = 1
    SCL_1; // SCL = 1
    SCL_Timeout();
    delay_us(I2CDELAYUSEC); // Quick delay
    ack = SDA_Timeout(); // Read ACK state from Slave
    SCL_0; // SCL = 0
    return ack;
    }

    static uint8_t SWI2CMST_rxByte(uint8_t ack)
    {
    uint8_t bits, data = 0;

    SDA_1; // SDA = 1
    bits = 0x08; // Load I2C bit counter
    while (bits > 0) // Loop until all bits are read
    {
    SCL_1; // SCL = 1
    SCL_Timeout();
    delay_us(I2CDELAYUSEC); // Quick delay
    data <<= 1; // Shift bits 1 place to the left
    if (SDA_READ) // Check digital input
    data++; // If input is high, store a '1'
    SCL_0; // SCL = 0
    delay_us(I2CDELAYUSEC); // Quick delay
    bits--; // Decrement I2C bit counter
    }
    if (ack) // Need to send ACK to Slave?
    SDA_0; // Yes, so pull SDA low
    else
    SDA_1; // No, so keep SDA high
    SCL_1; // SCL = 1
    delay_us(I2CDELAYUSEC); // Equivalent to sending N(ACK)
    SCL_0; // SCL = 0
    SDA_1; // SDA = 1

    return (data); // Return 8-bit data byte
    }

    uint16_t p=0;
    bool SWI2CMST_ReadReg(uint8_t SlaveAddress, uint8_t Cmd, void *Data, uint16_t Datalen)
    {
    uint16_t totallen;
    uint8_t *buff;
    //uint8_t buff[buff_size];
    bool status;

    if(Datalen>32)
    return false;

    #if (SWI2C_PEC_SUPPORTED == 1)
    if(Datalen>2)
    {
    totallen = Datalen + 5;//stt + addrw + cmd + stt + addrr + datalen + data0 ... +datan + pec + stp
    }
    else
    {
    totallen = Datalen + 4;//stt + addrw + cmd + stt + addrr + data0 + data1 + pec + stp
    }
    #else
    if(Data>2)
    {
    totallen = Datalen + 4;//stt + addrw + cmd + stt + addrr + datalen + data0 ... +datan + stp
    }
    else
    {
    totallen = Datalen + 3;//stt + addrw + cmd + stt + addrr + data0 + data1 + stp
    }
    #endif
    buff = (uint8_t *)malloc(buff_size);
    p=(uint16_t)buff;
    if(buff == NULL)
    return false;

    buff[0] = (SlaveAddress<<1);
    buff[1] = Cmd;
    buff[2] = (SlaveAddress<<1)+1;

    SWI2CMST_start(); // Send Start condition
    for (uint16_t i = 0; i < 2; i++)
    {
    status = SWI2CMST_txByte(buff[i]); // Send data and ack
    if(!status)
    break;
    }
    SWI2CMST_start(); // Send Start condition
    status = SWI2CMST_txByte(buff[2]); // Send data and ack
    for (uint16_t j = 0; j < (totallen-3); j++)
    {
    if(j == (totallen-4))
    {
    buff[3+j] = SWI2CMST_rxByte(NACK);
    }
    else
    {
    buff[3+j] = SWI2CMST_rxByte(ACK);
    }
    }
    SWI2CMST_stop(); // Yes, send STOP condition
    #if (SWI2C_PEC_SUPPORTED == 1)
    if(buff[totallen-1] != Check_CRC8(buff, totallen-1))
    {
    status = false;
    }
    else
    {
    if(Datalen>2)
    {
    buff += 4;
    totallen -= 5;
    //memcpy(Data, &buff[4], totallen-5);
    }
    else
    {
    buff += 3;
    totallen -= 4;
    //memcpy(Data, &buff[3], totallen-4);
    }

    memcpy(Data, buff, totallen);
    status = true;
    }
    #endif
    free(buff);
    return status;
    }

    uint8_t Check_CRC8(uint8_t *Pmsg, uint16_t Msg_Size)
    {
    uint16_t i, j, carry;
    uint8_t CRCData, msg;

    CRCData = *Pmsg++; // first byte loaded in "crc"
    for(i = 0 ; i < Msg_Size-1 ; i ++)
    {
    msg = *Pmsg++; // next byte loaded in "msg"
    for(j = 0 ; j < 8 ; j++)
    {
    carry = CRCData & 0x80; // check if MSB=1
    CRCData = (CRCData << 1) | (msg >> 7); // Shift 1 bit of next byte into crc
    if(carry) CRCData ^= 7; // If MSB = 1, perform XOR
    msg <<= 1; // Shift left msg byte by 1
    }
    }
    for(j = 0 ; j < 8 ; j++)
    {
    carry = CRCData & 0x80;
    CRCData <<= 1;
    if(carry) CRCData ^= 7;
    }

    return(CRCData);
    }

    swi2c.h -->

    #ifndef __SWI2C_H__
    #define __SWI2C_H__

    #include "io430.h"
    #include <stdint.h>
    #include <stdbool.h>


    #define PxSEL P4SEL // Port selection
    #define PxDIR P4DIR // Port direction
    #define PxOUT P4OUT // Port output
    #define PxIN P4IN // Port input

    #define SDA BIT4 // Controls SDA line
    #define SCL BIT5 // Controls SCL line


    #define  I2CDELAYUSEC  3 


    #define SDA_1 PxDIR&=~(SDA) // Set to input [SDA = 1 via pullup]
    #define SDA_0 PxDIR|=(SDA) // Set to output [SDA = 0]
    #define SCL_1 PxDIR&=~(SCL) // Set to input [SCL = 1 via pullup]
    #define SCL_0 PxDIR|=(SCL) // Set to output [SCL = 0]

    #define SDA_READ (PxIN & SDA)
    #define SCL_READ (PxIN & SCL)

    #define NACK 0
    #define ACK 1

    #define SWI2C_PEC_SUPPORTED (1)
    #define SWI2C_MAX_DATALEN (32)


    typedef struct
    {
    union
    {
    struct
    {
    uint8_t SCLTo : 1;//SCL拉低超时
    uint8_t WaitACKErr : 1;//等待应答超时
    uint8_t RSVD : 6;
    } bits;
    uint8_t Status;
    }byte;
    } I2CDrv_Status;


    void SWI2CMST_init(void);

    bool SWI2CMST_ReadReg(uint8_t SlaveAddress, uint8_t Cmd, void *Data, uint16_t Datalen);


    #endif

    main.c -->

    int main( void )
    {
    uint8_t txdata[32]={0};
    // Stop watchdog timer to prevent time out reset
    WDTCTL = WDTPW + WDTHOLD;

    SysClock_Init();

    SWI2CMST_init();




    while(1)
    {
    delay_ms(50);
    SWI2CMST_ReadReg(0x0B, 0x09, txdata, 2);
    }
    }

  • 您好,编译结果无错误。测试发现使用malloc free就会出现非法地址, 如果使用固定数组申请则正常,code详见1楼答复
  • 问题已解决,结贴。

    通过debug对内存地址追踪,发现malloc申请的起始地址在free前发生了改变,导致free释放错误,定位到问题点:如下

    对地址进行了操作

    解决办法:可另外定义一个临时指针地址和malloc相同,操作时仅对临时指针进行操作,free是可直接释放malloc的地址。如下:

    优化后的code:

    bool SWI2CMST_ReadReg(I2CDrv_Status *s, uint8_t SlaveAddress, uint8_t Cmd, void *Data, uint8_t Datalen)
    {
    uint8_t totallen;
    uint8_t *buff;//缓存空间指针
    uint8_t *temp;//临时指针
    bool status;

    if(Datalen>SWI2C_MAX_DATALEN)
    {
    s->byte.bits.DatalenErr=1;
    return false;
    }

    #if (SWI2C_PEC_SUPPORTED == 1)
    if(Datalen>2)
    {
    totallen = Datalen + 5;//stt + addrw + cmd + stt + addrr + datalen + data0 ... +datan + pec + stp
    }
    else
    {
    totallen = Datalen + 4;//stt + addrw + cmd + stt + addrr + data0 + data1 + pec + stp
    }
    #else
    if(Data>2)
    {
    totallen = Datalen + 4;//stt + addrw + cmd + stt + addrr + datalen + data0 ... +datan + stp
    }
    else
    {
    totallen = Datalen + 3;//stt + addrw + cmd + stt + addrr + data0 + data1 + stp
    }
    #endif
    buff = (uint8_t *)malloc(totallen);
    if(buff == NULL)
    return false;

    temp = buff;

    *temp = (SlaveAddress<<1);
    temp++;
    *temp = Cmd;
    temp++;
    *temp = (SlaveAddress<<1)+1;

    if(!SWI2CMST_start())
    {
    s->byte.bits.SCLLto=1;
    }
    else
    {
    s->byte.bits.SCLLto=0;
    }
    temp = buff;
    for (uint8_t i = 0; i < 2; i++)
    {
    status = SWI2CMST_txByte(*temp); // Send data and ack
    temp++;
    if(!status)
    {
    s->byte.bits.ACKErr=1;
    break;
    }
    s->byte.bits.ACKErr=0;
    }
    SWI2CMST_start(); // Send Start condition
    status = SWI2CMST_txByte(buff[2]); // Send data and ack
    for (uint8_t j = 0; j < (totallen-3); j++)
    {
    if(j == (totallen-4))
    {
    *temp = SWI2CMST_rxByte(NACK);
    }
    else
    {
    *temp = SWI2CMST_rxByte(ACK);
    temp++;
    }
    }
    SWI2CMST_stop(); // Yes, send STOP condition
    #if (SWI2C_PEC_SUPPORTED == 1)
    if(*temp != Check_CRC8(buff, totallen-1))
    {
    s->byte.bits.PECErr=1;
    status = false;
    }
    else
    {
    s->byte.bits.PECErr=0;
    if(Datalen>2)
    {
    temp += 4;
    totallen -= 5;
    }
    else
    {
    temp += 3;
    totallen -= 4;

    }
    memcpy(Data, temp, totallen);
    status = true;
    }
    #endif
    free(buff);
    return status;
    }

  • 感谢分享经验。这个是程序的逻辑问题。

  • 很高兴您能解决问题。谢谢分享!