I need to create a converter from epoch time stored in atime_t variable, to astruct tm variable, in order to check / create a certain task every hour or a day. This function should get also a pasttime_t for other uses.
Converting function, inside a library, works OK ( last two lines are for verification purposes, meaning conversion was done as expected ):
void myIOT32::convEpoch(time_t in_time, struct tm *convTime){ convTime = gmtime(&in_time); char time_char[40]; sprintf(time_char, "%04d-%02d-%02d %02d:%02d:%02d", convTime->tm_year + 1900, convTime->tm_mon+1, convTime->tm_mday, convTime->tm_hour, convTime->tm_min, convTime->tm_sec); Serial.print(" from funct: "); Serial.println(time_char);Now, when calling it from my code and try to use timetm var, it causes the code to crash. In code below, I just try to print it to console:
void sendnewNotif(){ struct tm *newtime; time_t t=182423032; iot.convEpoch(t, newtime); // <--- Using the conversion char timeStamp[50]; // Serial.print(newtime->tm_year); }What may be the problem ?
Guy
struct tm newtime;to alocate on stack.struct tm *newtimeis a pointer to nowhere2020-06-14 10:53:29 +00:00CommentedJun 14, 2020 at 10:53
1 Answer1
void myIOT32::convEpoch(time_t in_time, struct tm *convTime){ convTime = gmtime(&in_time);Here you are overwriting the parameterconvTime. There is no point inpassing such a parameter if you are not going to use the value provided.
void sendnewNotif(){ struct tm *newtime; time_t t=182423032; iot.convEpoch(t, newtime); // <--- Using the conversionnewtime is initially uninitialized. The call toiot.convEpoch()doesn't change that (the parameter is passed by value, not byreference).
Serial.print(newtime->tm_year);This is dereferencing an uninitialized pointer, which is undefinedbehavior and can crash the program.
The simplest solution I see is to havemyIOT32::convEpoch() return thepointer it got fromgmtime(). Note that this points to static storage,which makes the method not reentrant.
Example (not tested):
struct tm *myIOT32::convEpoch(time_t in_time){ struct tm *convTime = gmtime(&in_time); // ... return convTime;}void sendnewNotif(){ time_t t = 182423032; struct tm *newtime = iot.convEpoch(t); Serial.print(newtime->tm_year); }- thank you for your kind and comprehensive reply :), but your answer rised some more: a) why does it matter if it is initialized ? since it get its value later on ( though as a pointer ). b) are there guide lines when to use as a return value ( as you just suggested ) or as I did, passing its value/ reference ( in a case it works as expected... ) ?guyd– guyd2020-06-14 13:22:11 +00:00CommentedJun 14, 2020 at 13:22
- a) It does not get it's value later on. b) You could in principle pass the pointer by reference, but mixing pointers and references can quickly become highly confusing.Edgar Bonet– Edgar Bonet2020-06-14 15:11:50 +00:00CommentedJun 14, 2020 at 15:11
Explore related questions
See similar questions with these tags.

