0

With reference to the code below: After calling the function CheckSMS and passing the struct * DB1, the fields are updated according the the strtok call. This function reads and parses a text message, storing its contents into char* fields of the DB struct.

In the main loop, I have called Serial.println(DB1.last_order) before and after calling the CheckSMS function. If I have received a text, the order is printed appropriately in the main loop, however on the next call to CheckSMS, DB1.last_order is cleared, replaced with a \n or a NULL or something. I cannot figure out why DB1.last_order does not retain its value, and rather, it is overwritten with every call to CheckSMS. Thanks for any help.

Note - All text messages contain "CMT+", therefore writing to DB1 only happens when a text is received. Calling CheckSMS when no text is received should simply skip through.

  int CheckSMS(Robot *DB1) {

  int j = 0;
  char  response[100];
  char  *pch;
  unsigned long previous;

  memset(response, '\0', 100);

  while(Serial2.available()>0){
       response[j] = Serial2.read();
       j++;
       Serial.println("inc");
  }

  delay(100);
  if (strstr(response, "CMT:") != NULL){ 
      DB1->new_message = strtok(response, " ,");
      DB1->last_phone = strtok(NULL, " ,");
      pch = strtok(NULL, " ,");
      DB1->last_date = strtok(NULL, " ,");
      DB1->last_time = strtok(NULL, " ,\n");
      DB1->last_order = strtok(NULL," ,\n");
      new_message = 1;  

  }

  else{
  }

  return 0;
}
  • Assuming you actually read data, as soon as this function returns all the `char*` pointers you sucked out of those `strtok` calls and saved in `DB1` will be dangling (eg. no longer valid), as the buffer to which they reference (point into), `response[]`, no longer exists. [**This post**](https://stackoverflow.com/questions/6441218/can-a-local-variables-memory-be-accessed-outside-its-scope/6445794#6445794) is *seriously* worth a read. – WhozCraig Apr 15 '16 at 06:12

2 Answers2

2

The strtok function returns pointers to the string you're tokenizing, the local array response in your case. When the function returns the response array goes out of scope and disappears, leaving your structure with pointers to a string that no longer exists, and giving you undefined behavior.

You have a couple of solutions:

  • Allocate the string dynamically using malloc, but then you must save it in the structure so you can free it when you're done with the structure
  • Make the response array static, but then the next call to the function will have the same array leading the old data to be updated
  • Pass in a string to store the response and use that string, the string must have a lifetime at least as long as the structure and don't change contents. The string can of course be a member of the structure itself
Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
0

The answer Joachim gave is correct, I just want to add that you could also change the Robot structure to contain char arrays (like this: char new_message[MAX_BUF_CHARS]; and so on). Be sure to have enough space in them. Then instead of assigning the pointers returned from strtok, copy the strings in there.

Adrian Roman
  • 534
  • 4
  • 8