Jump to content

mktime behavior inconsistent with heap variable versus stack variable

- - - - -

  • Please log in to reply
3 replies to this topic

#1
Tronman

Tronman

    Newbie

  • Members
  • PipPip
  • 14 posts
Good day everybody,

I'm having some trouble with mktime giving me the correct Unix time stamp for some arbitrary time. After a bit of trial and error, I discovered that mktime behaves properly if I give it a pointer to a struct tm on the heap, but behaves inconsistently badly when given a reference to a stack variable. To help illustrate this, here is my code:

#include <iostream>
#include <sys/time.h>

int main(void)
{

  struct tm timeStruct;

  timeStruct.tm_year = 110;
  timeStruct.tm_mon = 10;
  timeStruct.tm_mday = 26;
  timeStruct.tm_hour = 0;
  timeStruct.tm_min = 10;
  timeStruct.tm_sec = 0;

  time_t resultUnix1 = mktime(&timeStruct);

  std::cout << "resultUnix1 = " << resultUnix1 << std::endl;

  struct tm * timeStructPtr = new tm;

  timeStructPtr->tm_year = 110;
  timeStructPtr->tm_mon = 10;
  timeStructPtr->tm_mday = 26;
  timeStructPtr->tm_hour = 0;
  timeStructPtr->tm_min = 10;
  timeStructPtr->tm_sec = 0;

  time_t resultUnix2 = mktime(timeStructPtr);

  std::cout << "resultUnix2 = " << resultUnix2 << std::endl;

  return 0;
}
And here is the output from two sample runs of the same code:

user@lucidlynx:~/Development$ ./mktime 
resultUnix1 = 1290744600
resultUnix2 = 1290744600
user@lucidlynx:~/Development$ ./mktime 
resultUnix1 = 1290741000
resultUnix2 = 1290744600
The second call, the one with the pointer, always returns the correct value. But the first call, the one passing a reference to the struct instead, seems to return the correct value about half of the time and an incorrect value (an hour earlier interestingly enough) the other half. It also changes the tm_mday, tm_hour, etc, from the timeStruct object passed in, to be consistent with the wrong unix timestamp it returned to me.

I'm at a lost to explain this behavior. Ideas anyone? I'm running my test program on Ubuntu 10.04 64-bit, Linux kernel 2.6.32-25-generic

Thanks!

#2
mnirahd

mnirahd

    Programming Professional

  • Members
  • PipPipPipPipPip
  • 330 posts
Hi,

I guess you need properly initialize the structure through memset before using it. Try following code, it worked for me


#include <iostream>

#include <sys/time.h>

#include <string.h>



int main(void)

{


  struct tm timeStruct;


[COLOR="Red"]  memset(&timeStruct, 0x00, sizeof(timeStruct));

[/COLOR]  timeStruct.tm_year = 110;

  timeStruct.tm_mon = 10;

  timeStruct.tm_mday = 26;

  timeStruct.tm_hour = 0;

  timeStruct.tm_min = 10;

  timeStruct.tm_sec = 0;


  time_t resultUnix1 = mktime(&timeStruct);


  std::cout << "resultUnix1 = " << resultUnix1 << std::endl;


  struct tm * timeStructPtr = new tm;


[COLOR="Red"]  memset(timeStructPtr, 0x00, sizeof(struct tm));

[/COLOR]  timeStructPtr->tm_year = 110;

  timeStructPtr->tm_mon = 10;

  timeStructPtr->tm_mday = 26;

  timeStructPtr->tm_hour = 0;

  timeStructPtr->tm_min = 10;

  timeStructPtr->tm_sec = 0;


  time_t resultUnix2 = mktime(timeStructPtr);


  std::cout << "resultUnix2 = " << resultUnix2 << std::endl;


  return 0;

}



Let me know if that works for you too!

Munir

#3
Tronman

Tronman

    Newbie

  • Members
  • PipPip
  • 14 posts

mnirahd said:

Hi,

I guess you need properly initialize the structure through memset before using it. Try following code, it worked for me

#include <iostream>
#include <sys/time.h>
#include <string.h>


int main(void)
{

  struct tm timeStruct;

[COLOR=Red]  memset(&timeStruct, 0x00, sizeof(timeStruct));
[/COLOR]  timeStruct.tm_year = 110;
  timeStruct.tm_mon = 10;
  timeStruct.tm_mday = 26;
  timeStruct.tm_hour = 0;
  timeStruct.tm_min = 10;
  timeStruct.tm_sec = 0;

  time_t resultUnix1 = mktime(&timeStruct);

  std::cout << "resultUnix1 = " << resultUnix1 << std::endl;

  struct tm * timeStructPtr = new tm;

[COLOR=Red]  memset(timeStructPtr, 0x00, sizeof(struct tm));
[/COLOR]  timeStructPtr->tm_year = 110;
  timeStructPtr->tm_mon = 10;
  timeStructPtr->tm_mday = 26;
  timeStructPtr->tm_hour = 0;
  timeStructPtr->tm_min = 10;
  timeStructPtr->tm_sec = 0;

  time_t resultUnix2 = mktime(timeStructPtr);

  std::cout << "resultUnix2 = " << resultUnix2 << std::endl;

  return 0;
}
Let me know if that works for you too!

Munir

Thanks for your help Munir. You were right of course, zeroing out the memory on the timeStruct solved the problem. New must have been zeroing out the memory for me which I didn't realize it did (and guessing it doesn't always), hence the apparent inconsistent behavior with stack vs heap. Still I wanted to know *what* piece of unallocated memory mktime was using since my understanding was it only used the "tm_year, tm_mon, etc" data members as input parameters, and the "tm_wday and tm_yday" as output parameters.

Turns out, there's an additional member of tm that I didn't know about: tm_isdst, which decides if it's going to auto correct for Daylight savings time or not. Depending on what happened to be in the buffer when it the stack value got allocated, it would either be arbitrarily true or false which would sometimes decide to the "hour previous" correct. So, mystery solved! Thanks again.

#4
mnirahd

mnirahd

    Programming Professional

  • Members
  • PipPipPipPipPip
  • 330 posts
thanks for telling the additional information regarding other members of tm struct!

cheers

Munir




1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users