Time.timeStr() sometimes returns empty

Hello,

I have an electron that has subscribed to an event where it always receives data in the format “message, id” where it looks like this: “1,64941349958349​”

I have a handler function that runs when it receives this data where the goal of the function is to
​1. Parse this data
2. Extract the message and id
3. Create a new char buffer that includes the extracted id and a timestmap
4. Publish that as a new event

However, sometimes the Time.timeStr() returns an empty timestamp. This is what the Serial monitor displays for the code provided below:

Message Received: 1,64941141915078
copy: 1,64941141915078
message: 1
id: 64941141915078
tnow:

Sending ack data:
64941141915078,

Notice how in this specific output, tnow is blank, thereby publishing an incomplete event. This happens once every few times. Could you please tell me why this is happening?
I usually receive 3 messages at once, spaced apart every 10 secs, in case this info is useful.

I very much appreciate your help!

Thanks,
Pasindu

void myHandler(const char *event, const char *data) {
    
    Serial.print("Message Received: ");
    Serial.println(data);
    
    char* saveptr;
    
    char* copy = strdup(data); 
    Serial.print("copy: ");
    Serial.println(copy);
    
    int message = atoi(strtok_r(copy, ",", &saveptr)); // using strtok_r instead of strtok because strtok uses global pointer and causes problems when threading
    Serial.print("message: ");
    Serial.println(message);
	
    char* id = strtok_r(NULL, ",", &saveptr);
    Serial.print("id: ");
    Serial.println(id);
    
    
    const char* tnow = Time.timeStr(); // store timestamp in tnow
    Serial.print("tnow: ");
    Serial.println(tnow);
    
    char buffer[strlen(id) + strlen(tnow) + 2]; // create a buffer that's the length of the id, timestamp, and 2 more spaces (for a comma and a NULL termination character)
    
    strcpy(buffer,id); // copy id into buffer along with NULL ternimation character automatically
    strcat(buffer,","); // concatinate a comma into buffer which overwrites NULL ternimation and rewrites it at the end
    strcat(buffer,tnow); // concatinate timestamp into buffer which overwrites NULL ternimation and rewrites it at the end

    Serial.println();
    Serial.println("Sending ack data:");
    Serial.println(buffer);
    Serial.println();
    
    Particle.publish("ackdata", buffer , 60, PRIVATE);
    
    free(copy);

}

Do you know how long the string at tnow will live there?
How does that behave, if you pull a copy of that string - I’d rather do that with strcpy() and a char[] array (since you know the length already) to avoid heap fragmentation.
I’d do the same for copy for the same reason.

Hmm, are you saying that the pointer tnow won’t live until the end of the function?

But by doing something like:

char cpyoftnow [26]
strcpy(cpynow, tnow)

you are suggesting that it will now live until the end?

The pointer will live, but the contents of the RAM location might not. I’ve no comprehension where Time actually creates the string, but if it’s in a system buffer, a parallel thread might overwrite it.


Update
I’ve looked up the implementation of Time.timeStr()

/* return string representation for the given time */
String TimeClass::timeStr(time_t t)
{
	t += time_zone_cache;
    t += dst_current_cache;
	tm* calendar_time = localtime(&t);
        char* ascstr = asctime(calendar_time);
        int len = strlen(ascstr);
        ascstr[len-1] = 0; // remove final newline
	return String(ascstr);
}

If you catch the returned String object instead of the pointer you might prolong its live time as well.

Ah, thank you! That does make sense.

And the
char cpyoftnow [26]
strcpy(cpynow, tnow)
should take care of this like you said, right?

I’d rather do

  char cpyoftnow[26];
  strncpy(cpyofnow, Time.timeStr(), sizeof(cpyoftnow));

or

  char cpyoftnow[32];
  snprintf(cpyofnow, sizeof(cpyoftnow), "tnow: %s", (const char*)Time.timeStr());

Thank you tons!
I think I like the snprintf version better.

I feel as if strncpy is rarely used anymore. As if people avoid using it.