[Solved] Strtok() resets core

Can someone please help me with why the following code causes my spark cores to reset loop/crash?

char *test = "word1-word2";
char *p;

void setup() {

  Serial.begin(115200);
  Serial.println("Starting..");
  
   //  First strtok iteration
   p = strtok(test,"-");
   Serial.print(p);
   Serial.print(" ");

   //  Second strtok iteration
   p = strtok(NULL,"-");
   Serial.print(p);
   Serial.println("");

}

void loop () {
}

Hi @keithblack

You should always test p to see if it is NULL before trying to use it. I believe the second call to strtok is returning NULL and when you try to print that, bad things happen.

Thanks for the quick reply @bko but the following resets core also?
I’ve tried many different ways of using strtok() but keeping getting forced resets?

char *test = "word1-word2";
char *p;

void setup() {

  Serial.begin(115200);
  Serial.println("Starting..");
  
   //  First strtok iteration
   p = strtok(test,"-");
   Serial.print(p);
   Serial.print(" ");

//   //  Second strtok iteration
//   p = strtok(NULL,"-");
//   Serial.print(p);
//   Serial.println("");

}

void loop () {
}

I’ve never had these problems with strtok(), so it might be a completely different problem.

Do you get any Serial.print() output?
Can you try Serial.println(test); to ensure the string is stored correctly?
Can you try to flash a completely different firmware (e.g. blink LED) to make sure, you haven’t got a bad firmware stuck in your Core and you don’t really see this behaviour caused by this code but by some other that keeps the Core from being reflashed correctly?

BTW, I think the second strtok() shouldn’t return NULL, since '\0' is a default delimiter for strtok(), otherwise you’d never get the final token returned propperly.

Now I think I got the reason.

I was wrong :blush: - it IS strtok().
It’s the way how strtok() works. With each iteration strtok() tries to replace the next found delimiter with '\0'. But since you’ve set *test in the global var declaration, *test points to a flash address, which can’t be altered and so the replacement attempt will fail and obviously crash the Core.

3 Likes

Bingo @ScruffR–well done!

So try

char test[] = "word1-word2";  //heap allocated NOT const in flash

And please do test the return values against NULL for safety. There is only one delimiter in your test string, so I still think the second call would return NULL.

2 Likes

The final token discussion is an ever reoccuring :wink:
But these two links may help settling it (only exemplarily)

http://www.cplusplus.com/reference/cstring/strtok/

BUT sure, testing for NULL pointers is always good practice!


I’ll never stop learning :wink:
@bko, I didn’t know that

char szHeap[] = "sometext";
char *zsFlash = "sometext";

are actually that different.
Thanks for the insight! :+1:

I will certainly stand corrected on the tokenization! Thanks for that.

But a better parsing program structure would be more like this:

   int fieldn=0; //count of parsed fields
   char * p = strtok(dataStr, delimiterStr);
   while (p != NULL) {
        //some code here to deal with the token possibly using the field number
        //...
        fieldn++;
        p = strtok(NULL, delimiterStr); // next please!
    }
1 Like

That did the trick!

Thanks @bko and @ScruffR

char test[] = "word1-word2";  //heap allocated NOT const in flash
1 Like