Thread: I can't tell what is wrong with this code ARRR!

  1. #16
    Temporal Apparition qubit67's Avatar
    Join Date
    Jan 2007
    Posts
    85
    I added the if (ch == '\n') break; as the first statement within the while loop with -- if (i > 0) buffer[i] = '\0' first statement outside the loop for when we have a string and encounter an EOF at the end. The last statement is to free and return NULL if the first character encountered on calling get_line is an EOF. Does this system sound right to you guys?

    Will it still bypass the problem :

    "If your line is exactly the same lenght as whatever buffer_size you have when you find the newline, the if to check for the i == buffersize will be missed out, and then you will write to buffer[buffersize] which is one byte too far." ?


    GDB shows no errors, I am yet to upload and test with the big index 1 000 000+ entries to get_line from the file into a BST.

  2. #17
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    Dunno, without you post your latest code.
    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.

  3. #18
    Temporal Apparition qubit67's Avatar
    Join Date
    Jan 2007
    Posts
    85
    sorry :
    Code:
    char *get_line(FILE *file) 
    {
    	FILE *fp = file;
    	
    	char *buffer;
    	int ch,  i=0;
    	unsigned int buffer_size = BUFFER_SIZE, new_buffer_size;
    
    	assert(buffer_size > 0);
    
    	buffer = (char *) safe_malloc (buffer_size * sizeof (char));
    	
    	while ((ch = getc(fp)) != EOF )
    	{
    		
    		if (ch == '\n')			 
    			break;
    			
    		if (buffer_size == i) 
    		{
    			new_buffer_size = buffer_size * 2;
    			assert(new_buffer_size >= buffer_size);
    			buffer = (char *) safe_realloc (buffer, new_buffer_size * sizeof (char));
    			buffer_size = new_buffer_size;
    		}
    		buffer[i] = ch;
    		i++;
    		
    	}
    	if (i > 0)
    	{
    		buffer [i] = '\0';
    		return buffer;
    	}
    	else
    	{
    		free(buffer);
    		return NULL;
    	}
    }

  4. #19
    Registered User
    Join Date
    Aug 2005
    Location
    Austria
    Posts
    1,990
    that check after the while loop is wrong.
    you don't check if the '\0' still fits into the buffer.
    Kurt
    EDIT: I would return an empty string ( buffer[0]=0; ) in case nothing was input. This way the calling function would not have to check the returnvalue for NULL. ( just like the c++ getline ).
    Last edited by ZuK; 09-15-2007 at 11:52 AM.

  5. #20
    Temporal Apparition qubit67's Avatar
    Join Date
    Jan 2007
    Posts
    85
    Code:
    char *get_line(FILE *file) 
    {
    	FILE *fp = file;
    	
    	char *buffer;
    	int ch,  i=0;
    	unsigned int buffer_size = BUFFER_SIZE, new_buffer_size;
    
    	assert(buffer_size > 0);
    
    	buffer = (char *) safe_malloc (buffer_size * sizeof (char));
    	
    	while ((ch = getc(fp)) != EOF )
    	{
    		
    		
    		if (buffer_size == i) 
    		{
    			new_buffer_size = buffer_size * 2;
    			assert(new_buffer_size >= buffer_size);
    			buffer = (char *) safe_realloc (buffer, new_buffer_size * sizeof (char));
    			buffer_size = new_buffer_size;
    		}
    		
                                if (ch == '\n')			 
    		break;
    			
                                buffer[i] = ch;
    		i++;
    	}
    	if (i > 0)
    	{
    		buffer [i] = '\0';
    		return buffer;
    	}
    	else
    	{
    		free(buffer);
    		return NULL;
    	}
    }
    The function needs to return NULL if the index file is empty so I dont know if returning an empty string would work.

    The specs for this function are:

    "get_line reads a single line of text from its argument file pointer. If the EOF is encountered
    immediately without reading any characters from the file, the NULL pointer should be
    returned. Otherwise a pointer to a dynamically allocated string should be returned. The
    string must be large enough to fit an entire line of input. Lines are ended by the newline
    character, or when the EOF is encountered. Ending newline characters should be read in by
    the function, but they should NOT be stored in the string which is returned. For example,
    if the file contains these characters:
    123\n456\n78
    The last character in the file is 8, and any attempt to read input after that character will
    result in EOF. The first call to get_line on the file will return a string containing these
    characters:
    123\0
    6
    The second call to get_line on the file will return a string containing these characters:
    456\0
    The third call to get_line on the file will return a string containing these characters:
    78\0 "

    The '\n' is taken care of with regard to allocating the correct buffer_size to the string for storage of the sentinal now that it is included in the body.

    My problem is with the EOF, how do I make sure there is space for it if the loop terminates at the EOF and doesnt allocate space for a final NULL, when the case is that EOF is found at the end of a string and buffer_size is unable to be changed?

    I hope I make sense....
    Last edited by qubit67; 09-15-2007 at 10:41 PM. Reason: code error

  6. #21
    Temporal Apparition qubit67's Avatar
    Join Date
    Jan 2007
    Posts
    85
    It seems my code from the previous post is working!
    Thanks a billion to all those who coached/helped/advised me on this matter.

    Please comment if you think i can still further optimise my function within the parameters of the specs

  7. #22
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    > It seems my code from the previous post is working!
    So you fixed this ?
    > how do I make sure there is space for it if the loop terminates at the EOF and doesnt allocate space for a final NULL

    If you make sure the string is always \0 terminated in the loop, the problem goes away.

    > buffer = (char *) safe_realloc (buffer, new_buffer_size * sizeof (char));
    1. Why are you casting the alloc functions in C anyway - see the FAQ
    2. I assume this is just a thin wrapper around realloc

    If you do p = realloc ( p, newsize ); and it fails (returns NULL) then your code is broken and you have a memory leak.
    It is much better to write
    Code:
    void *temp = realloc ( p, newsize );
    if ( temp != NULL ) {
      p = temp;
    } else {
      // panic, no more memory available, but p is still valid.
      // options could be
      // 1. free(p) and bail with return NULL
      // 2. return p "as is"
      // something else
    }
    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. #23
    Temporal Apparition qubit67's Avatar
    Join Date
    Jan 2007
    Posts
    85
    yes thanks Salem, I have a fully working function.

    I dont think that i can always terminate the string with a null within the loop because getc stops when it reaches the EOF, the loop is broken before I can insert a NULL so I have to do it outside... right?

    Safe realloc is a thin wrapper :
    Code:
    void *safe_realloc (void *old, size_t bytes)
    {
       void *new;
    
       assert (bytes > 0);
    
       if ((new = realloc (old, bytes)) == NULL)
       {
          fprintf (stderr, "Fatal memory allocation failure, aborting\n");
          exit (EXIT_FAILURE);
       }
       return new;
    }
    to deal have realloc behave more safely.

    I thought i needed to cast a void pointer to the type on return... right/wrong?

  9. #24
    Woof, woof! zacs7's Avatar
    Join Date
    Mar 2007
    Location
    Australia
    Posts
    3,459
    Wrong.

    BTW, NULL is for pointers, NUL is the nul-terminating character, 0, '\0'...

  10. #25
    Temporal Apparition qubit67's Avatar
    Join Date
    Jan 2007
    Posts
    85
    tnx zacs7, I looked through the term, and suddenly... it all became clearer.... and for casting malloc, Salem, point agreed, will ammend my code.
    qubz

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. what is wrong in this simple code
    By vikingcarioca in forum C Programming
    Replies: 4
    Last Post: 04-23-2009, 07:10 AM
  2. what is wrong with this code please
    By korbitz in forum Windows Programming
    Replies: 3
    Last Post: 03-05-2004, 10:11 AM
  3. I cant find what is wrong with this code
    By senegene in forum C Programming
    Replies: 1
    Last Post: 11-12-2002, 06:32 PM
  4. Anyone see what is wrong with this code?
    By Wise1 in forum C Programming
    Replies: 2
    Last Post: 02-13-2002, 02:01 PM
  5. very simple code, please check to see whats wrong
    By Unregistered in forum C Programming
    Replies: 3
    Last Post: 10-10-2001, 12:51 AM