0

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

askedJun 14, 2020 at 9:54
guyd's user avatar
1
  • struct tm newtime; to alocate on stack.struct tm *newtime is a pointer to nowhereCommentedJun 14, 2020 at 10:53

1 Answer1

1
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 conversion

newtime 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); }
answeredJun 14, 2020 at 10:07
Edgar Bonet's user avatar
2
  • 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... ) ?CommentedJun 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.CommentedJun 14, 2020 at 15:11

Your Answer

Sign up orlog in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

By clicking “Post Your Answer”, you agree to ourterms of service and acknowledge you have read ourprivacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.