如题,在使用malloc申请内存是地址会出现非法地址,程序处理完后有做free释放。堆栈设置
调试如图
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.
您好,感谢回复。
测试发现使用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);
}
}
问题已解决,结贴。
通过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;
}