0

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
1
  • 1
    My answer has nothing to do with your problem, and neither does your code, apparently. I copied it and ran it, and it worked perfectly. You must do something you do not show us. Commented Sep 13, 2012 at 12:57

3 Answers 3

6

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.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for the reply @joachim-pileborg. after using 0 like startDate->tm_sec = 0; in all the places gives the same error.
following is the output >>>GetLaterDate before dt1=20100810 dt2=20100810 >>>dateDiff_Days >>>GetLaterDate before dt1=NULLNULL dt2=NULLNULL >>>GetLaterDate before tempDt1=NULLNULL tempDt2=NULLNULL after calling dateDiff_Days the string dt1 and dt2 are getting corrupted
1

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.

Comments

1

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy 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.