user1668585
user1668585

Reputation: 1

string is getting corrupted after using the time functions

i have written a datediff in days function which return the number of days for two dates (input format is 20100810)

after running the program my input strings are getting corrupted, unable to understand where i am doing it wrong.

I am running this on AIX, when i run this on Redhat string is not getting corrupted.

Following is the code

#include <iostream>
#include <ctime> 
#include <sstream>
using namespace std;

int GetYear(std::string dateStr)
{
std::string year = dateStr.substr (0,4);
int sYr = atoi(year.c_str());
//std::cout <<"<<<GetYear dateStr:"<< dateStr << " yearStr:"<< year <<", int sYr:" << sYr << std::endl;
return sYr;
}


int GetMonth(std::string dateStr)
{
 //std::cout <<">>>GetMonth dateStr:"<< dateStr << std::endl;
 int sMn =0;
 std::string mm = dateStr.substr (4,2);
 sMn = atoi(mm.c_str());
// std::cout <<"<<<GetMonth dateStr:"<< dateStr <<"MonthStr:"<< mm <<", int MM:" << sMn << std::endl;
 return sMn;
}

int GetDay(std::string dateStr)
{
 //std::cout << ">>>GetDay dateStr:"<< dateStr << std::endl;
 int sDy = 0;
 std::string dd = dateStr.substr (6,2);
 sDy = atoi(dd.c_str());
 //std::cout << "<<<GetDay dateStr:"<< dateStr<<" DayStr:"<< dd <<", int DD:" << sDy << std::endl;
 return sDy;
}


int dateDiff_Days (std::string startStr,std::string endStr){
std::cout << ">>>dateDiff_Days" << std::endl; 
int sYr;
 int eYr;
 int sMn;
 int eMn;
 int sDy;
 int eDy;
 time_t end;
 time_t start;
 struct tm *startDate;
 struct tm *endDate;
 int dif;
 int i =0;
//Move over the start date to string and convert string to int
 sYr = GetYear(startStr);
 sMn = GetMonth(startStr);
 sDy = GetDay(startStr);
//Move over the end date to string and convert string to int
 eYr = GetYear(endStr);      
 eMn = GetMonth(endStr);
 eDy = GetDay(endStr);
//Move information into startDate structure
start = time(0);
  startDate = localtime (&start); 
  startDate->tm_year = (sYr-1900);  //Years since 1900
  startDate->tm_mday = sDy;          //Day of the month: 1-31
  startDate->tm_mon = sMn-1;           //Months since Jan: 0-11
//Leave default zero's in for the rest
  startDate->tm_sec = '0';           
  startDate->tm_min = '0';
  startDate->tm_hour = '0';
  startDate->tm_wday = '0';
  startDate->tm_yday = '0';
  startDate->tm_isdst = '0';
  start = mktime (startDate);

//Move info into endDate structure, same as startDate.
end = time(0);
  endDate = localtime (&end);
  endDate->tm_year = (eYr-1900);
  endDate->tm_mday = eDy;
  endDate->tm_mon = eMn-1;
  endDate->tm_sec = '0';
  endDate->tm_min = '0';
  endDate->tm_hour = '0';
  endDate->tm_wday = '0';
  endDate->tm_yday = '0';
  endDate->tm_isdst = '0';
  end = mktime (endDate);

  dif = difftime (end, start);
  dif = dif/86400;
 return dif;

}   
int main (){

std::string dt1 = "20100810";
std::string dt2 = "20100810";

        std::cout << ">>>GetLaterDate before dt1="<< dt1 <<" dt2="<< dt2 << std::endl;   
        std::string tempDt1 (dt1);
        std::string tempDt2 (dt2);
        int i = dateDiff_Days(dt1,dt2);
        std::cout << ">>>GetLaterDate before dt1="<< dt1 <<" dt2="<< dt2 << std::endl; 
        std::cout << ">>>GetLaterDate before tempDt1="<< tempDt1 <<"   tempDt2="<< tempDt2 << std::endl; 
return 0;
}

Output:

>>>GetLaterDate before dt1=20100810 dt2=20100810
>>>dateDiff_Days
>>>GetLaterDate before dt1=NULLNULL dt2=NULLNULL
>>>GetLaterDate before tempDt1=NULLNULL tempDt2=NULLNULL

Upvotes: 0

Views: 544

Answers (3)

Abhay Bhave
Abhay Bhave

Reputation: 44

localtime and gmtime use statically allocated struct tm instance. That means call to any of them may alter tm values whose address is (as you have) kept in another pointer in an expectation that the call will ALLOCATE a tm for you and return address.

According to the "return value" section of this doc (http://www.cplusplus.com/reference/ctime/localtime/)

The returned value points to an internal object whose validity or value may be altered by any subsequent call to gmtime or localtime.

Instead of just capturing addresses (most probably same each time) returned by multiple calls to those functions, you should have that address, allocate another tm and have the values copied to it. Let the time functions play with the static instance as they do. :)

Hope it helps.

Upvotes: 1

paddy
paddy

Reputation: 63501

As a side note, it's really not necessary to call time and localtime just to get a pointer to a struct tm when you're gonna overwrite that anyway. You should do this:

struct tm ttm;

memset(&ttm, 0, sizeof(ttm));
ttm.tm_year = sYr - 1900;
ttm.tm_mon = sMn - 1;
ttm.tm_mday = sDy;
time_t start = mktime( &ttm );

memset(&ttm, 0, sizeof(ttm));    // Because mktime can alter the struct
ttm.tm_year = eYr - 1900;
ttm.tm_mon = eMn - 1;
ttm.tm_mday = eDy;
time_t end = mktime( &ttm );

I don't know if it's possible that you're corrupting the heap because localtime is returning something bogus. Maybe. Try what I've given here anyway, and at the very least it's better practice even if it doesn't fix your problem.

Upvotes: 1

Some programmer dude
Some programmer dude

Reputation: 409482

Almost all the lines where you initialize the tm structures are wrong, like this one:

startDate->tm_sec = '0';

This actually sets startDate->tm_sec to 48. The fields are integers not characters.

Upvotes: 6

Related Questions