cancel
Showing results for 
Search instead for 
Did you mean: 

Hard fault when using std::string substr() in this situation

max239955
Associate II
Posted on July 27, 2017 at 11:55

Hey guys,

I have a function that parses messages of my own format and splits them into an opcode and (0-3) operands.

With 0 or 1 operand, it works fine; on the second operand, the 

msg.substr(start, (pos - start)); causes a hard fault every time without fail on my STM32F4. Stepping into substr() in the debugger it appears to occur inside the constructor for basic_string. I tested the code in an online compiler and it works fine, so I'm guessing it's some kind of memory allocation issue. Just doesn't make sense to me that it works for the first operand and not the second. Any ideas guys?

You'll also notice some commented out use of std::vector. This is another issue with STM32 C++ development in Keil I believe which I could also do with help sorting - currently any call to push_back kills the program (possibly a similar issue to above?).

#include <iostream>

#include <string>

#include <stdexcept>

void ParseMessage(const std::string msg)

{

   std::string opCode;

   //std::vector<std::string> operands;

   std::string operands[3];

   uint8_t operandCount = 0;

   opCode = msg.substr(1, 3);

   std::cout << 'Opcode: ' << opCode << std::endl;

   if(msg[4] == '#') {

      // We have at least one operand

      size_t pos;

      size_t start = 5;

      pos = msg.find('#', start);

      while(pos != std::string::npos) {

         operands[operandCount++] = msg.substr(start, (pos - start));

         std::cout << 'Operand ' << operandCount << ': ' << operands[operandCount-1] << std::endl;

         // Store middle operands

         //operands.push_back(msg.substr(start, pos - 1));

         start = pos + 1;

         pos = msg.find('#', start);

      }

      // Store the final operand

      //operands.push_back(msg.substr(start, msg.length() - 2));

      //uint16_t tmp = msg.length();

      operands[operandCount++] = msg.substr(start, ((msg.length() - 1) - start));

      std::cout << 'Operand ' << operandCount << ': ' << operands[operandCount-1] << std::endl;

   }

}

int main()

{

     ParseMessage('<SSG#0.7#0.3#0.05>');

   return 0;

}
4 REPLIES 4
AvaTar
Lead
Posted on July 27, 2017 at 13:33

A stack overflow, probably.

I don't expect the C++ stdio and string functions to be more memory-economical than the printf-style clib functions.

Posted on July 27, 2017 at 16:04

Use a proper Hard Fault handler and identify exactly what code itis breaking on, these are gross failures and shouldn't be hard to pin down. Look at the assembler code, the faulting instruction, the registers, and those specifically used by the instruction in question.

https://community.st.com/0D50X00009XkeRmSAJ

For Keil the stack size is defined in startup_stm32f4xx.s, C++ likely also expects a sufficiently large heap.

Unaligned LDRD/STRD will fault. Accessing bogus addresses will fail. So bad pointers, strings that aren't NUL terminated, corrupt stack, stack/heap collision.

Most likely a fault in your logic/algorithm. Build some test cases, test them on a PC platform.

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
Posted on July 27, 2017 at 14:25

So is there I can do about it?

Note that the std::cout calls are just there for when i tested it on an online compiler

Posted on July 27, 2017 at 15:24

Increase stack size, or do your parsing in a less resource-consuming manner.

But before, I would check SCB registers in the hardfault case.