Thread: Delete problem when compiled in C++

  1. #1
    Registered User
    Join Date
    Jun 2007
    Posts
    4

    Delete problem when compiled in C++

    Before I begin, this is the code for a function I wrote:

    Code:
    #include <string.h>
    #include <stdlib.h>
    #include "dtio.h"
    
    int dt_edit(char *se, int slen, int row, int col, int flen,int *start, int *offset, int *insert, int ctype) {
       int key=0, pos = strlen(se), cpos=*start, i, done=1;
       char * origstring = NULL; /*Will hold copy of se*/
       char * temp = NULL; /*Temporary Buffer for the string*/
       char letter; /*temporary character for INS*/
       int offval = *offset;
       int startval = *start;
       int min, max, j, ctypechk=0;
       
    
       /*Temp is the output buffer for dt_draw( )*/
       /*Note, extra DMA is required for this assignment*/
    
    #ifdef __cplusplus
       temp = new char[flen+1];
       origstring = new char[(slen != 0) ? slen+1 : flen-1];
    #else
       temp = (char*) malloc(sizeof(char)*(flen+1));
       origstring  = (char*) malloc(sizeof(char)* (slen != 0) ? (slen+1) : (flen-1));
    #endif
      
      /*min and max are coordinates on the se for displaying. */
      min = offval;
      max = min + flen - 1;
      pos=startval+offval;
    
    /*No code will be processed if the DMA fails, returns a null byte if it fails*/
    if(temp && origstring)
    {
      updatescreen(min, max, temp, se, row, col, flen);
      dt_cursor(row, col+cpos);
    
      /*Backup of the original string*/
      strcpy(origstring, se);
    
      /*Before editing can occur, this segment will "clean the buffer and put origstring into se
        (workaround to a display bug in the ctype tests!)*/
         for (i = strlen(se); i>=0; i--)
    	se[i]=' ';
         strcpy(se, origstring);
    
       key = dt_getkey( );
       while(done==1) {
    	 switch(key) {
    	   case PGUP:
    	   case PGDN:
    	   case F1:
    	   case F2:
    	   case F3:
    	   case F4:
    	   case F5:
    	   case F6:
    	   case F7:
    	   case F8:
    	   case F9:
    	   case F10:
    	   case TAB:
    	   case UP:
    	   case DOWN:
    	   case ENTER:
    	   done = 0;
    	   break;
    	    /*Restores string to beginning of function's default*/
    	    case ESC:
    		 /*Before restoring can occur, this segment will "clean the buffer and put
    		   origstring into se (workaround to a display bug in the ctype tests!)*/
    		 for (i = strlen(se); i>=0; i--)
    		   se[i]=' ';
    		 strcpy(se, origstring);
    		 min = offval;
    		 max = min + flen - 1;
    		 pos=startval+offval;
    		 cpos = startval;
    		 updatescreen(min, max, temp, se, row, col, flen);
    		 dt_cursor(row, col+cpos);
    		 done = 0;
    	    break;
    
    	    /*Scrolls to the left*/
    	    case LEFT:
    		 if(cpos > 0)
    		 {
    		   pos--;cpos--;
    		 }
    		 else
    		 {
    		    if(min > 0)
    		    {
    			 pos--;min--;max--;
    			 updatescreen(min, max, temp, se, row, col, flen);
    
    			 /*Find new null byte location (if string small)*/
    			 for(i=min, j=0; i<=max+1 && j == 0; i++)
    			 {
    			    if(!se[i])
    			    {
    				 max = strlen(se);
    				 j++;
    			    }
    			    else
    			    {
    				 max = min + flen - 1;
    			    }
    			 }
    		    }
    		 }
    	    dt_cursor(row, cpos+col);
    	    key = dt_getkey( );
    	    break;
    
    	    case RIGHT:
    		   if(cpos < flen - 1 && pos != strlen(se))
    		   {
    			pos++;cpos++;
    		   }
    		   else
    		   {
    			  if(pos < strlen(se))
    			  {
    				pos++;min++;max++;
    				updatescreen(min, max, temp, se, row, col, flen);
    
    			  }
    
    		   }
    		   dt_cursor(row, cpos+col);
    		   key = dt_getkey( );
    	    break;
    
    	    case HOME:
    		 max = (strlen(se) < flen) ? strlen(se) : flen - 1;
    		 pos = cpos = min = 0;
    
    		 updatescreen(min, max, temp, se, row, col, flen);
    
    		 dt_cursor(row, cpos+col);
    		 key = dt_getkey( );
    	    break;
    
    	    case END:
    		  max = strlen(se) + 1;
    		  cpos = (strlen(se) < flen) ? strlen(se) : flen - 1;
    		  min = (max < flen) ? 0 : max - flen;
    		  pos = max - 1;
    
    		  updatescreen(min, max, temp, se, row, col, flen);
    
    
    		  dt_cursor(row, col+cpos);
    		  key = dt_getkey( );
    	    break;
    
    	    case DEL:
    		  if(pos < strlen(se))
    		  {
    			 max -= (max > strlen(se)) ? 1 : 0;
    
    			 for(i=pos; i<strlen(se); i++)
    			   se[i] = se[i+1];
    
    			 updatescreen(min, max, temp, se, row, col, flen);
    
    
    			 dt_cursor(row, cpos+col);
    		  }
    		  key = dt_getkey( );
    	    break;
    
    	    case BS:
    		  if(pos > 0)
    		  {
    			 cpos -= (cpos == 0) ? 0 : 1;
    			 max -= (max > strlen(se)) ? 1 : 0;
    			 min -= (cpos == 0 && min != 0) ? 1 : 0;
    			 pos--;
    
    			 for(i=pos; i<strlen(se); i++)
    			   se[i] = se[i+1];
    
    			 updatescreen(min, max, temp, se, row, col, flen);
    
    			 /*Find new null byte location (if string small)*/
    			 for(i=min, j=0; i<=max+1 && j == 0; i++)
    			 {
    			    if(!se[i])
    			    {
    				 max = strlen(se);
    				 j++;
    			    }
    			    else
    			    {
    				 max = min + flen - 1;
    			    }
    			 }
    			 dt_draw(temp, row, col, flen);
    			 dt_cursor(row, cpos+col);
    		  }
    		  key = dt_getkey( );
    	    break;
    	    case INS:
    		  *insert = (*insert == 1) ? 0 : 1;
    		   key = dt_getkey( );
    	    break;
    
    	    default:
    		  switch(ctype){
    		  case 1:  ctypechk = (key>=' ' && key<='~') ? 1 : 0;
    				 break;
    		  case 2:  ctypechk = (key=='0' || key=='1') ? 1 : 0;
    				 break;
    		  case 4:  ctypechk = (key>='0' && key<='9') ? 1 : 0;
    				 break;
    		  case 8:  ctypechk = (key>='0' && key<='7') ? 1 : 0;
    				 break;
    		  case 16: ctypechk = ((key>='0' && key<='9') || (key>='A' && key<='F')) ? 1 : 0;
    
    		  /*I allowed the use of lower case typing, it will convert to upper case, I did
    		    this for easier typing and you didnt mention in your specs with that scenario
    		    (I asked some CPA students and they said go for it! GG Bitshift 4tw)*/
    		  key ^= (key>='a' && key<='f') ? 32 : 0;
    		  ctypechk = ((key>='0' && key<='9') || (key>='A' && key<='F')) ? 1 : 0;
    				 break;
    		  default: ctypechk = 0;}
    		  /*printf("&#37;c, %d",key, ctypechk);*/
    		  if(ctypechk)
    		  {
    		    /*Insert Mode*/
    		    if(*insert == 1)
    		    {
    			 /*Will only add characters if the field has not exceeded*/
    			 if(strlen(se) < slen)
    			 {
    			   /*increments if its at the end of the window*/
    			   if(cpos == flen - 1)
    			   {
    				 min++; max++;
    			   }
    			   else{cpos++;}
    
    			   /*Changes max if the string is too small (safeguard)*/
    			   for(i=min, j=0; i<=max && j == 0; i++)
    			   {
    			    if(!se[i])
    			    {
    				 max = strlen(se);
    				 j++;
    			    }
    			    else
    			    {
    				 max = min + flen - 1;
    			    }
    			   }
    
    			   /* copying chars into 'actual' array backwards */
    			   se[strlen(se)+1] = '\0';
    			   for(i=strlen(se); i>pos; i--)
    			   {
    				 se[i] = se[i-1];
    			   }
    			   se[pos] = key;
    			   updatescreen(min, max, temp, se, row, col, flen);
    			   pos++;
    			 }
    			 dt_cursor(row, cpos+col);
    		    }
    
    
    		  /*Overstrike Mode*/
    		  else
    		  {
    
    			/*will only allow input of characters if pos is not at the limiter */
    			 max -= (strlen(se) == slen) ? 1 : 0;
    			 for(i=min, j=0; i<=max && j == 0; i++)
    			 {
    			    if(!se[i])
    			    {
    				 max = strlen(se);
    				 j++;
    			    }
    			    else
    			    {
    				 max = min + flen - 1;
    			    }
    			 }
    
    			 if(cpos == flen - 1)
    			 {
    			   min++;
    			 }
    			 else{cpos++;}
    
    			 /*If the cursor isnt at the end and goes beyond the allocated length, it
    			   will "Do nothing" (chars can still be put in overstrike)*/
    			 if(!se[pos] && strlen(se) == slen)
    			 {
    			   se[pos] = '\0';
    			   pos--;
    			   min--;
    			   max--;
    			 }
    			 /*If the string is too small, but its at the end, it will write a nullbyte
    			   at that location ahead of it and overwrite the current null with a character
    			   (bug fix for the ctype tests and other displays)*/
    			 else if(!se[pos] && strlen(se) < slen)
    			 {
    			   se[pos+1] = '\0';
    			   se[pos] = key;
    			 }
    			 /*anywhere else*/
    			 else
    			 {
    			   se[pos] = key;
    			 }
    			 pos++;
    
    			 updatescreen(min, max, temp, se, row, col, flen);
    			 dt_cursor(row, cpos+col);
    
    		  }
    	   }
    	 key = dt_getkey( );
    	}
       }
       /*Nukes memory that was allocated*/
       #ifdef __cplusplus
           /*if(temp) delete [ ] temp;
           if(origstring) delete [ ] origstring;*/      
       #else
           free(temp);
           free(origstring);
       #endif
      }/*end of if for DMA*/
       return key;
    }
    
    void updatescreen(int min, int max, char * temp, char * se, int row, int col, int flen)
    {
      int i, j;
    
       /*Debug code, decided to keep it for later use*/
       /*char msg[121];
       sprintf(msg, "min: %d max:%d flen:%d se:%d", min, max, flen, strlen(se));
       dt_cursor(24, 30);
       dt_putstring(msg);
       dt_cursor(row, col);*/
    
      for(i=min, j=0; i<=max+1 && se[i]; i++, j++)
        temp[j] = se[i];
    
      for( ; j<flen; j++)
        temp[j] = ' ';
    
      temp[j+1] = '\0';
      dt_draw(temp, row, col, flen);
    }
    I do admit it is a tad bit long, but its functionality is simple. It allows the user to use Direct Terminal I/O on a string. All the code within works except for the bolded text when its uncommented.

    I know its kinda strange that I used #define __cplusplus twice (for DMA) but I am aware of the defects that malloc( ) has when used in C++. But I had some extern reference problems and this is how I decided to counter it.

    When I try to delete temp and/or origstring, I get something involving glibc and an invalid next call(fast) along with the address where it crashed. The odd thing is, this only happens on a c++ compile (and I need this to compile with another C++ program I have). On C, this program has no problems, it will do the malloc and not detect the new/delete (which can only be done in c++)

    I don't really want to have memory leaks so would anyone know what the problem might be and/or how to fix it, I have been thinking that the 2 memory blocks are either corrupted or I did something wrong calculating the memory I desire.
    Last edited by Hellwolf_36; 06-02-2007 at 02:55 PM.

  2. #2
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    Without DTIO, I can't do much with that.

    But this is counter to the usual idiom:
    Code:
       for ( i=min, j=0; i<=max+1 && se[i]; i++, j++ )
    So my first guess is that you step off the end of the array and you're already in the land of undefined behavior. When you attempt to delete[] stuff it's telling you that you've hosed the memory by kindly crashing out.

    Or at least that's my take.
    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.*

  3. #3
    Registered User
    Join Date
    Jun 2007
    Posts
    4
    Min and max are limiters for which parts of the text should be displayed. For instance, if min was 0 and max was 7, it would display the first 7 characters of the string. But I don't think that is the problem, because that part compiles on C and C++ and they both work fine, even after periods of navigating or hitting any key.

    If that was the case, I would have gotten a segmentation fault instead.

    But doesn't delete [ ] (variable name) go to the first address of the array and continue forth.

  4. #4
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    I'll try to take your word for it, but things like this
    Code:
    se[strlen(se)+1] = '\0';
    look suspicious as hell. "Go one beyond the null terminator and null terminate it again."

    And as you've noticed, it's not a compile-time thing, it's a run-time thing. So the fact that it compiles means little.
    If that was the case, I would have gotten a segmentation fault instead.
    As far as defining UB, well, that's contrary to UB.

    I think you're trying to diagnose a symptom, not the disease.
    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.*

  5. #5
    Registered User
    Join Date
    Jun 2007
    Posts
    4
    I know I am being difficult there. But se[strlen(se)+1] shifts the null over one (if it can) then moves all the text over 1 to the spot where a letter needs to be added. At that spot, it throws in what you typed.

    If I didn't put that there. I would have caused a Segmentation Fault by removing the limit for the field. And believe me, I learned that one the hard way
    Last edited by Hellwolf_36; 06-02-2007 at 04:52 PM.

  6. #6
    Registered User
    Join Date
    May 2006
    Posts
    903
    This is ridiculous. You could have used the insert() member function of the string class. Do you *really* need to support both languages ?

  7. #7
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    One curiosity: if you take out calls to updatescreen and have the delete[] code in, is the same behavior observed?
    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.*

  8. #8
    Registered User
    Join Date
    Jun 2007
    Posts
    4
    Updatescreen( ) takes temp (the allocated memory) and displays text it has formed from the min and max modifers. If that function holds delete [ ] temp;, then my program would segmentation fault if I were to press any key except for the termination keys (The case: F1 and onward). If I were to take them out, then nothing will be displayed on the screen.

    Code:
    void updatescreen(int min, int max, char * temp, char * se, int row, int col, int flen)
    min is the first character of the segment.
    max is the last character of the segment.
    Temp is the string that will be outputted to the screen at row/col
    SE is the entire string, min and max will take a portion of se and put it in temp for dt_draw( ) (which simply outputs the text)
    row and col are obvious, where the string will be displayed.
    Flen is the length of the field itself.

    Since the specs needed dt_draw( ) and I knew what it does, I decided to play around with it and score a 2nd allocation.


    Quote Originally Posted by Desolation
    This is ridiculous. You could have used the insert() member function of the string class. Do you *really* need to support both languages ?
    Yeah it has to. But insert( ) would write the first set of characters. This will screw up scrolling, but will help in HOME.
    Last edited by Hellwolf_36; 06-03-2007 at 03:26 PM.

  9. #9
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    Quote Originally Posted by Hellwolf_36 View Post
    Updatescreen( ) takes temp (the allocated memory) and displays text it has formed from the min and max modifers. If that function holds delete [ ] temp;
    Let me clarify. If you uncomment the delete where you have it, but remove calls to updatescreen, and then proceed with input etc. as usual, does the problem still exist? That is, is the bug in updatescreen?
    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.*

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Proper Usage of the delete Operator
    By thetinman in forum C++ Programming
    Replies: 7
    Last Post: 04-25-2007, 11:53 PM
  2. Bin packing problem....
    By 81N4RY_DR460N in forum C++ Programming
    Replies: 0
    Last Post: 08-01-2005, 05:20 AM
  3. delete and delete []
    By Lionel in forum C++ Programming
    Replies: 8
    Last Post: 05-19-2005, 01:52 PM
  4. Problem with Tutorial #2
    By Keiyentai in forum Windows Programming
    Replies: 2
    Last Post: 03-20-2005, 06:38 PM
  5. question about .net to 6.0 change causing errors
    By jverkoey in forum C++ Programming
    Replies: 17
    Last Post: 03-23-2004, 10:45 AM