Ezra .M
Ezra .M

Reputation: 11

Fixing a Memory Overwrite errors likely due to malloc on an STM32 Nucleo-F334R8

I hope this is a clear explanation of my issue I've been runnign around various manuals for a little over a week now tryign to solve this:

Recently I have been redesigning a software design for a class project after feedback and testing on the STM32 Nucleo-F334R8(my initial code was riddled with memory and timing errors)

Currently I run into two main errors:

(This issue has been resolved)

I had been using sprintf not accounting for the trailing null character writting outside of allocated memory.

When processing USART Data using USART 1 in Asynchronous mode at 115200 Baudrate:

Program received signal SIGTRAP, Trace/breakpoint trap. 0x08002c08 in memset ()

Program received signal SIGTRAP, Trace/breakpoint trap. 0x08002c08 in memset ()

Program received signal SIGTRAP, Trace/breakpoint trap. 0x08002c08 in memset ()

Program received signal SIGTRAP, Trace/breakpoint trap. 0x08002c08 in memset ()

Program received signal SIGTRAP, Trace/breakpoint trap. 0x080056b4 in std.isra ()

The value stored at the address 0x08002c08 in question is usually very large typically something like 134228385 in decimal. Also if I forcefully step through the issue the program continues to run fine and never encounters the problem again which I find strange possible cause?

UPDATE: So I've traced the memset issue around a bit and found that it occurs during my setOutputBuffer method:

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)

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

I encountered a breakpoint trap while filling the bss segment of the board's memory

And after adding Seven GPIO Ports for a 4bit mode LCD(namely PA12, PA11, PB12, PB11, PB2, PB1, PB15) and two for a two channel ADC in DMA mode (PA1, PA0):

Program received signal SIGTRAP, Trace/breakpoint trap. LoopFillZerobss () at ..\startup/startup_stm32f334x8.s:103 103 cmp r2, r3 While trying to implement LCD and ADC functionality I receive the breakpoint trap error during the LoopFillZerobss function of startup which proved fatal, particularly by stopping my USART from reporting at all(however it can still receive bytes as interrupt and process tokens etc, just refuses to transmit), After reading up into the bss segment I attempted to solve the issue by initializing as many global variables as I could to non-zero values, this did not work, the problem is observed after adding the STM32CubeMx settings for ADC and the 7 GPIO pins used in the LCD, however none of these use unitialized variables to my knowledge unless the predefined code generated by CubeMX is going beyond the bounds of the bss segment of memory and that the size of the bss segment is too large now for the board's memory (which I suspect is unlikely but can't rule out).

Essentially the idea of this project is to receive various data over USART, ADC and later I2C and display various aspects of the data over USART and LCD at currently if I discard the ADC and LCD errors my USART code functions as the memset() error is non-lethal but I suspect that leaving it there is only causing me later issues but I'm also not sure where to fix my tokenizing code, assuming it is the root of my issues.

Upvotes: 0

Views: 816

Answers (1)

Ezra .M
Ezra .M

Reputation: 11

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

By ensuring to use snprintf rather than sprintf with well defined sized strings I ran into no more memory issues.

Upvotes: 1

Related Questions