修复内存覆盖错误可能是由于STM32 Nucleo-F334R8上的malloc引起的

问题描述 投票:0回答:1

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

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

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

(This issue has been resolved)

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

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

程序接收信号SIGTRAP,跟踪/断点陷阱。 memset()中的0x08002c08

程序接收信号SIGTRAP,跟踪/断点陷阱。 memset()中的0x08002c08

程序接收信号SIGTRAP,跟踪/断点陷阱。 memset()中的0x08002c08

程序接收信号SIGTRAP,跟踪/断点陷阱。 memset()中的0x08002c08

程序接收信号SIGTRAP,跟踪/断点陷阱。 std.isra中的0x080056b4()

存储在地址0x08002c08中的值通常非常大,通常为十进制的134228385。此外,如果我强行执行该问题,该程序继续运行正常,再也没有遇到问题,我觉得奇怪的可能原因?

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

String>,%5d,%8s,%3d,%3d,%3d,%4d,%4d,%4d,%10.6f,%11.6f,%7.1f,%3d,%3.1f\n",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] = '$';
} ```

(This issue has been resolved)

基本上我的问题的根源是滥用sprintf并用空字符覆盖程序代码

我在填充电路板内存的bss段时遇到了断点陷阱

为4位模式LCD(即PA12,PA11,PB12,PB11,PB2,PB1,PB15)添加7个GPIO端口后,为DMA模式下的双通道ADC(PA1,PA0)添加2个:

程序接收信号SIGTRAP,跟踪/断点陷阱。 LoopF​​illZerobss()at .. \ startup / startup_stm32f334x8.s:103 103 cmp r2,r3在尝试实现LCD和ADC功能时,我在启动的LoopF​​illZerobss函数期间收到断点陷阱错误,这被证明是致命的,特别是通过阻止我的USART报告完全(但它仍然可以接收字节作为中断和处理令牌等,只是拒绝传输),在读入bss段后,我试图通过初始化尽可能多的全局变量来解决问题,非零值,这不起作用,在添加ADC的STM32CubeMx设置和LCD中使用的7个GPIO引脚后会出现问题,但是除非CubeMX生成的预定义代码超出了CubeMX的范围,否则它们都不会使用单元化变量。 bss段的内存和bss段的大小现在对于板的内存来说太大了(我怀疑它不太可能但不能排除)。

基本上这个项目的想法是通过USART,ADC和后来的I2C接收各种数据,并在当前如果我丢弃ADC和LCD错误的USART和LCD上显示数据的各个方面我的USART代码用作memset()错误是非致命但我怀疑留下它只会导致我后来的问题,但我也不知道在哪里修复我的令牌化代码,假设它是我的问题的根源。

c embedded stm32 truestudio
1个回答
0
投票

Essentially the source of my problem was misuse of sprintf and overwritting program code with null characters

通过确保使用snprintf而不是sprintf和明确定义的字符串,我遇到了更多的内存问题。

© www.soinside.com 2019 - 2024. All rights reserved.