Thread: Results in Debug and Release mode are different

  1. #1
    Registered User jaro's Avatar
    Join Date
    Mar 2006
    Location
    In my Parent House
    Posts
    34

    Results in Debug and Release mode are different

    Hi!,

    I've created three functions that would work together in order to generate a date is string YYYY-MM-DD format.
    The code works fine in Debug mode.The problem is when I try to run this code in the Release mode.
    It (the program) gives me two different results when I run it in Debug and Release mode.
    And no compile error and warning are present when I compile it in those two modes respectively.


    here is the code
    Code:
    #include <string.h>
    #include <stdio.h>
    #include <time.h>
    
    #define HOUR 261
    #define MINUTE 262
    #define DAY 263
    #define MONTH 264
    #define YEAR 265
    
    
    void padUpString(char *str, char* filler, int len, int fillAtTheEnd)
    {
    
    	int i;
    	char newstr[50]="";
    	
    	int strLen = strlen(str);
    	int diff = len - strLen;
    
    
    	if (strLen < len)
    	{
    		for (i=0; i< len ; i++)
    		{
    			if (fillAtTheEnd)
    			{
    				if( i >= strLen) *(str+strLen++)=*filler;
    			}else
    			{
    			     if( i < diff) strcat(newstr,filler);
    
    			}
    		}
    		if (!fillAtTheEnd)
    		{
    			strcat(newstr,str);
    			strcpy(str,newstr);
    		}
    	}
    }
    
    
    int getCurrentTimeValue(int timeElement)
    {
    	struct tm *tm_today;
    	time_t t;
    
    	t = time(NULL);
    	tm_today = localtime(&t);
    	//printf("timeElement is %d\n",timeElement);
    
    	if (timeElement == HOUR)
    	{
    		return tm_today->tm_hour;
    	}
    	if (timeElement == MINUTE)
    	{
    		return tm_today->tm_min;
    	}
    	if (timeElement == DAY)
    	{
    		//printf("DAY is %d\n",timeElement); //for debug purposes
    		return tm_today->tm_mday;
    	}
    	if (timeElement == MONTH)
    	{
    		//printf("MONTH is %d\n",timeElement);//for debug purposes
    		return tm_today->tm_mon + 1;
    	}
    	if (timeElement == YEAR)
    	{
    		//printf("YEAR is %d\n",timeElement);//for debug purposes
    		return tm_today->tm_year + 1900;
    	}
    	return -1;
    }
    
    
    void getProcessDate(char *procDate)
    {
    	//YYYY-MM-DD
    	char currentTime[11];
    	char year[4];
    	char day[2];
    	char month[2];
    
    	sprintf(year,"%d",getCurrentTimeValue(YEAR));
    	sprintf(month,"%d",getCurrentTimeValue(MONTH));
    	sprintf(day,"%d",getCurrentTimeValue(DAY));
    
    	printf("\nCheck date\n"); // for testing purpose only
    	printf("year [%s]\n",year);
    	printf("month [%s]\n",month);
    	printf("day [%s]\n",day);
    
    
    	padUpString(month,"0",2,0);
    	padUpString(day,"0",2,0);
    
    	printf("\nAfter padding\n");// for testing purpose only
    	printf("month [%s]\n",month);
    	printf("day [%s]\n",day);
    
    	sprintf(currentTime,"%s-%s-%s",year,month,day);
    	currentTime[10] = '\0';
    	memcpy(procDate,currentTime,sizeof(currentTime));
    }
    
    
    int main()
    {
    	char date[30];
    	getProcessDate(date);
    	printf("%s\n",date);
    	return 0;
    
    }

    the output
    Debug Mode
    Check date
    year [2006]
    month [5]
    day [24]

    After padding
    month [05]
    day [24]
    2006-05-24
    Release Mode
    Check date
    year [2006]
    month []
    day [24]

    After padding
    month [00]
    day [2400]
    -00-2400

    as you can see the "month" in Release mode is blank,which I suspect is the one causing the problem.

    Does anyone know why the results are different?
    and how would I fix such problem?

    I'm using MVC6 in Win2K

    Regards,
    jaro
    Last edited by jaro; 05-24-2006 at 05:20 AM. Reason: forgot to include tool being used

  2. #2
    erstwhile
    Join Date
    Jan 2002
    Posts
    2,227
    These kind of variations are often caused by not initialising variables prior to use. In 'debug' mode they will be automatically set to some neutral, reproducible value (NULL, zero, empty string, etc) but this does not occur automatically for 'release' builds.
    CProgramming FAQ
    Caution: this person may be a carrier of the misinformation virus.

  3. #3
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    Instead of overcomplicating things, why not use strftime?
    https://cboard.cprogramming.com/showthread.php?p=262899

    [edit]Didn't realize this was also posted to another forum.
    Last edited by Dave_Sinkula; 05-24-2006 at 07:49 AM.
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  4. #4
    Registered User jaro's Avatar
    Join Date
    Mar 2006
    Location
    In my Parent House
    Posts
    34
    Quote Originally Posted by Dave_Sinkula
    Instead of overcomplicating things, why not use strftime?
    https://cboard.cprogramming.com/showthread.php?p=262899
    I should better read more on standard function in C. This is the 2nd time that Dave have pointed me to an existing function in C. And as always using strftime() did help alot.

    Anyway I did found out what is cause the problem that I mention in my first post ( actually someone pointed to me the problem ).

    In the getProcessDate function, the array declaration is wrong. I failed to include space for the null terminator in array declaration.

    Changing the declaration from
    Code:
    char year[4];
    char day[2];
    char month[2];
    To this
    Code:
    char year[5];
    char day[3];
    char month[3];
    Solve the problem in running the program in Release mode.
    Although I'm curious to why this kind of error is not present in Debug mode.

    here are the changes in the code that I've made and also with the strftime() solution.

    Code:
    #include <string.h>
    #include <stdio.h>
    #include <time.h>
    
    #define HOUR 261
    #define MINUTE 262
    #define DAY 263
    #define MONTH 264
    #define YEAR 265
    
    
    void padUpString(char *str, char* filler, int len, int fillAtTheEnd)
    {
    
    	int i;
    	char newstr[50]="";
    	
    	int strLen = strlen(str);
    	int diff = len - strLen;
    
    
    	if (strLen < len)
    	{
    		for (i=0; i< len ; i++)
    		{
    			if (fillAtTheEnd)
    			{
    				if( i >= strLen) *(str+strLen++)=*filler;
    			}else
    			{
    			     if( i < diff) strcat(newstr,filler);
    
    			}
    		}
    		if (!fillAtTheEnd)
    		{
    			strcat(newstr,str);
    			strcpy(str,newstr);
    		}
    	}
    }
    
    
    int getCurrentTimeValue(int timeElement)
    {
    	struct tm *tm_today;
    	time_t t;
    
    	t = time(NULL);
    	tm_today = localtime(&t);
    
    	if (timeElement == HOUR)
    	{
    		return tm_today->tm_hour;
    	}
    	if (timeElement == MINUTE)
    	{
    		return tm_today->tm_min;
    	}
    	if (timeElement == DAY)
    	{
    		return tm_today->tm_mday;
    	}
    	if (timeElement == MONTH)
    	{
    		return tm_today->tm_mon + 1;
    	}
    	if (timeElement == YEAR)
    	{
    		return tm_today->tm_year + 1900;
    	}
    	return -1;
    }
    
    
    void getProcessDate(char *procDate)
    {
    	//YYYY-MM-DD
    	char currentTime[11];
    	char year[5];
    	char day[3];
    	char month[3];
    
    	sprintf(year,"%d",getCurrentTimeValue(YEAR));
    	sprintf(month,"%d",getCurrentTimeValue(MONTH));
    	sprintf(day,"%d",getCurrentTimeValue(DAY));
    
    
    	padUpString(month,"0",2,0);
    	padUpString(day,"0",2,0);
    
    	sprintf(currentTime,"%s-%s-%s",year,month,day);
    	currentTime[10] = '\0';
    	memcpy(procDate,currentTime,sizeof(currentTime));
    }
    
    
    void getProcessDateTwo(char *procDate){
    	//YYYYMMDD
    	char currentTime[11];
    	time_t tval;
    	struct tm *tmptr;
    	
    	tval = time(NULL);
    	tmptr = localtime(&tval);
    	
    	strftime(currentTime,sizeof(currentTime),"%Y-%m-%d",tmptr);
    
    	currentTime[10] = '\0';
    	memcpy(procDate,currentTime,sizeof(currentTime));
    	//return currentTime;
    }
    
    
    int main()
    {
    	char date[30];
    	char dateTwo[30];
    
    	getProcessDate(date);
    	getProcessDateTwo(dateTwo);
    
    	printf("getProcessDate %s\n",date);
    	printf("getProcessDateTwo %s \n",dateTwo);
    
    	return 0;
    
    }
    OutPut
    getProcessDate 2006-05-24
    getProcessDateTwo 2006-05-24
    the getProcessDateTwo function uses the strftime(). Same result when running in Release and Debug mode.


    regards,
    jaro

  5. #5
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    You could just write directly into the target rather than into a local and then copying it.
    Code:
    #include <stdio.h>
    #include <time.h>
    
    char *timestamp(char *stamp, size_t size)
    {
       time_t now;
       if ( time(&now) != (time_t)(-1) )
       {
          struct tm *today = localtime(&now);
          if ( today != NULL )
          {
             const char format[] = "%Y-%m-%d";
             if ( strftime(stamp, size, format, today) )
             {
                return stamp;
             }
          }
       }
       return 0;
    }
    
    int main(void)
    {
       char stamp[11];
       if ( timestamp(stamp, sizeof stamp) )
       {
          printf("stamp = \"%s\"\n", stamp);
       }
       return 0;
    }
    
    /* my output 
    stamp = "2006-05-24"
    */
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  6. #6
    Registered User jaro's Avatar
    Join Date
    Mar 2006
    Location
    In my Parent House
    Posts
    34
    Made some changes as you've suggested

    Code:
    void getProcessDateTwo(char *procDate){
    	//YYYYMMDD
    	
    	time_t tval;
    	struct tm *tmptr;
    	
    	tval = time(NULL);
    	tmptr = localtime(&tval);
    	
    	if(!strftime(procDate,11,"%Y-%m-%d",tmptr))
    	{
    		printf("error in getting date");
    	}
    
    }
    I've left out some of the error checking methods.

    Regards,
    jaro

  7. #7
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    > Made some changes as you've suggested
    It's a pity you didn't take Dave's post "as is".
    At least it passes the length of the target buffer in a meaningful way rather than just assuming it's always 11 (like you do).
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  8. #8
    Registered User jaro's Avatar
    Join Date
    Mar 2006
    Location
    In my Parent House
    Posts
    34
    Quote Originally Posted by Salem
    It's a pity you didn't take Dave's post "as is".
    At least it passes the length of the target buffer in a meaningful way rather than just assuming it's always 11 (like you do).
    the length of the target buffer will always be 11, so I decided to make it a constant.

    It is not that I didn't take Dave advice to write directly into the target.
    I did find Dave advice very useful. Especially now that I want to expand the getProcessDateTwo() in returning different date format.

    Many thanks to those who replied.

    regards,
    Jaro

  9. #9
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    It's you Y10K bug, not mine

    What if you edit your time format string to something else?

    Sure you can get away with it now, but writing bug-free code is in part a habit of always doing the right thing even when it apparently doesn't matter whether you take a short-cut or not.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  10. #10
    Registered User jaro's Avatar
    Join Date
    Mar 2006
    Location
    In my Parent House
    Posts
    34
    Quote Originally Posted by Salem
    It's you Y10K bug, not mine

    What if you edit your time format string to something else?

    Sure you can get away with it now, but writing bug-free code is in part a habit of always doing the right thing even when it apparently doesn't matter whether you take a short-cut or not.
    Point well taken.
    I'll make the changes as necessary (as in this case use Dave sample as is ).

    Thanks for the wake up call

    -jaro

  11. #11
    Fountain of knowledge.
    Join Date
    May 2006
    Posts
    794
    Quote Originally Posted by jaro
    Solve the problem in running the program in Release mode.
    Although I'm curious to why this kind of error is not present in Debug mode.
    jaro
    It fairly common for a program to work in debug mode but not
    without. I don't know the exact reason but I suspect a lot of
    extra code is put in for debug purposes which shifts where
    the program and data are. So if you were overwriting (accidently)
    an area of memory that area would be shifted. Is seems
    in your case that either extra debug data has been added
    between the variables or the variables have been reordered or
    moved. Also it is possible that in debug mode it will not allow
    you to write past the end of a string. A lazy way to avoid problem
    such as yours is just to make strings much longer than necessary
    in the first place ie

    Code:
    char year10];
    char day[10];
    char month[10];
    A bit inefficient but it can save you a lot of grief!!

  12. #12
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    So, you think it's a good idea to make your strings longer than you need to, in the hopes that your buffer overflow won't overwrite something you shouldn't? You'd be better off just fixing the buffer overrun.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 4
    Last Post: 09-16-2006, 07:11 PM
  2. release vs debug mode
    By bithub in forum Tech Board
    Replies: 2
    Last Post: 05-10-2006, 03:31 PM
  3. Release vs. Debug mode builds
    By earth_angel in forum C++ Programming
    Replies: 5
    Last Post: 11-10-2005, 04:41 PM
  4. Debug Mode Vs. Release Mode
    By incognito in forum Tech Board
    Replies: 5
    Last Post: 12-18-2003, 04:06 PM
  5. 2min in debug mode, 3sec in release!
    By glUser3f in forum C++ Programming
    Replies: 9
    Last Post: 10-03-2003, 01:00 PM