C语言 修复可能由于STM32核-F334R8上的malloc引起的内存覆盖错误



我希望这是对我的问题的明确解释,我已经在各种手册中运行了一个多星期,现在试图解决这个问题:

最近,在对STM32 Nucleo-F334R8进行反馈和测试后,我一直在为一个班级项目重新设计软件设计(我的初始代码充满了内存和时序错误)

目前我遇到了两个主要错误:

(此问题已解决)

我一直在使用 sprintf,而不考虑分配内存之外的尾随空字符写入。

在异步模式下使用 USART 1 处理 USART 数据时,在 115200波特率:

程序接收信号SIGTRAP,跟踪/断点陷阱。 0x08002c08 内存集 ()

程序接收信号SIGTRAP,跟踪/断点陷阱。 0x08002c08 内存集 ()

程序接收信号SIGTRAP,跟踪/断点陷阱。 0x08002c08 内存集 ()

程序接收信号SIGTRAP,跟踪/断点陷阱。 0x08002c08 内存集 ()

程序接收信号SIGTRAP,跟踪/断点陷阱。 0x080056b4 标准伊斯拉 ()

存储在相关地址0x08002c08的值通常非常 大通常类似于十进制的134228385。另外,如果我 强行逐步解决问题,程序继续运行良好 再也不会遇到我觉得奇怪的问题 可能的原因?

更新:所以 我已经跟踪了一下内存集问题,发现它发生了 在我的setOutputBuffer方法中:

String>,%5d,%8s,%3d,%3d,%3d,%4d,%4d,%4d,%10.6f,%11.6f,%7.1f,%3d,%3.1fn",uptime,timeString,temperature,pressure,humidity,acc1,acc2,acc3,latitude,longitude,altitude,current,voltage);
} ``` Which leads me to believe the issue lies in finding a value that
is being used to set the Output buffer message.
I would like advice on how to further troubleshoot these two issues
and whether there is a chance that the memset error is related the
later bss error.
My String Tokenizing code(edited):
```c void tokenize(char* in){     const char *p = in;     const char 
delim[] = ",";    char *token = NULL;     uint8_t n = 0;
do{
size_t length = strcspn(p, delim);      if(length > 0){             if(token ==
NULL){
token = malloc(sizeof(char)*length); // create memory space for the token
memset(token, 0, length); // ensure initialized memory is blank
sprintf(token, "%.*s",(int)length,p); // store the token from a substring of Input Buffer
p+=length; // move pointer to next ','
parseToken(token, n); // extract information from the token be it latitude, longitude etc
memset(token, 0, length); // clear the token
free(token); // free up the token's spot in memory
token = NULL; // set token pointer to null
n++;            }
}

}while(*((++p)+1) != '*'); // The expected string ends with a
checksum character '*' after the last ',' } ``` I've re-examined the
function and made a lot of changes now I can successfully step through
the entire function without issue, the program then returns to my main
loop, and I let it run for a while but then I suddenly run back into
the same memset issue, even without receiving any bytes over USART
here is the code for my main loop and the subsequent function calls it
makes:
```c
while (1)   {
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
if (byteFlag){          byteRecieved();             byteFlag = 0;       }
if(msgFlag){            msgRecieved();          msgFlag = 0;        }
if(secFlag){            setOutputBuffer();          HAL_UART_Transmit(&huart1,
(uint8_t *)bufferOut, 91, 1000);          secFlag = 0;        }
} ``` byteReceived: ```c if((char) byteIn == '$'){
clearInputBuffer();     } else if((char) byteIn == 'n'){
msgFlag = 1;    }
else{       storeChar();    } ```
msgReceived: ```c if(isValid()){      if (checksum()) {
tokenize(bufferIn);             clearInputBuffer();         }   } ```
isValid: ```c char substr[5];     strncpy(substr, (bufferIn+1), 5);
if(!strcmp(substr, "GPGGA")){       return 1;   }
return 0; ```
checksum: ```c int checksum(){    int calc_checksum = 0;  int
in_checksum;  int i = 0;  char checkstr[2];   uint8_t hasCheckSum = 0;
for(int j = 0; j<91; j++){      if (bufferIn[j] == '*') {           hasCheckSum
= 1;          i = 1;      }   }
if (hasCheckSum) {      while (bufferIn[i] != '*'){             calc_checksum ^=
bufferIn[i];          i++;        }       checkstr[0] = bufferIn[i+1];        checkstr[1]
= bufferIn[i+2];  } else {return 0;}

in_checksum = parseStr_HexToInt(checkstr);
if (calc_checksum == in_checksum){      return 1;   } else {        return 0;
} } ```
clearInputBuffer: ```c void clearInputBuffer(){   int i = 0;
for(i = 0; i < 100; i++){       bufferIn[i] = ' ';  }   bufferIn[0] = '$';
} ```

(此问题已解决)

从本质上讲,我问题的根源是滥用sprintf并用空字符重写程序代码

我在填充 bss 段时遇到了断点陷阱 董事会的记忆

在为 4 位模式 LCD(即 PA12)添加七个 GPIO 端口后, PA11、PB12、PB11、PB2、PB1、PB15)和两个用于DMA中的双通道ADC 模式 (PA1, PA0):

程序接收信号SIGTRAP,跟踪/断点陷阱。 LoopFillZerobss () at ..\startup/startup_stm32f334x8.s:103 103 CMP R2, r3 在尝试实现 LCD 和 ADC 功能时,我在 LoopFillZerobss 函数期间收到断点陷阱错误 事实证明是致命的创业公司,特别是通过阻止我的USART来启动 从报告(但是它仍然可以接收字节作为 中断和处理令牌等,只是拒绝传输),之后 阅读 bss 部分,我试图通过以下方式解决问题 将尽可能多的全局变量初始化为非零值, 这不起作用,添加 ADC的STM32CubeMx设置和LCD中使用的7个GPIO引脚, 然而,据我所知,这些都没有使用单位化变量 除非 CubeMX 生成的预定义代码超出了 BSS 段的内存边界和 BSS 的大小 段现在对于板的内存来说太大了(我怀疑是 不太可能,但不能排除)。

从本质上讲,这个项目的想法是通过 USART、ADC 和后来的 I2C 接收各种数据,并显示当前通过 USART 和 LCD 的数据的各个方面,如果我丢弃 ADC 和 LCD 错误,我的 USART 代码功能,因为 memset() 错误是非致命的,但我怀疑把它留在那里只会导致我以后的问题,但我也不确定在哪里修复我的标记化代码, 假设这是我问题的根源。

从本质上讲,我问题的根源是滥用 sprintf 并使用空字符重写程序代码

通过确保使用snprintf而不是sprintf定义大小的字符串,我不再遇到内存问题。

最新更新