Thread: opening empty file causes access violation

  1. #1
    Registered User
    Join Date
    Jan 2008
    Posts
    15

    opening empty file causes access violation

    Hey there guys,

    I have written a program to open a file, read from it and store the data into a structure. The program works fine except when i try to use an empty file to read from the program stops responding, and after debugging it, DEV c++ says that an access violation segmentation fault has been raised in the program. Im not really sure where to start, whether its to do with the opening of the file or whether is is to do with reading in the data. Any help would be great. here is the data for the test file if anyone wants to see how it works.
    ----------------------------------------------------
    1 25 1 Sisters Anniversary
    0 5 7 Mums Birthday
    1 25 2
    0 16 12 My Birthday
    1 6 7 Nans and Grandads Anniversary
    ---------------------------------------------------

    Code:
    // included libraries
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    //------------------------------------------------------------------------------
    
    //------------------------------------------------------------------------------
    // constants
    const char *MONTHS[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", 
                            "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; 
                            //array of months
    const int ARRAY_LENGTH = 5;// array length
    const int DESC_LENGTH=256;
    //------------------------------------------------------------------------------
    
    //structures--------------------------------------------------------------------
    struct EventDate {
           int day;
           int month;
           };
           
    enum EventType {Birthday, Anniversary};
    
    struct Event {
           EventType type;
           EventDate date;
           char description[DESC_LENGTH];
           };
    //------------------------------------------------------------------------------
    
    //------------------------------------------------------------------------------
    // Function prototypes
    
    FILE *safeOpen(char *fileName, char *mode);
    // Purpose:   To safely open a file
    // Arguments: the file name of the file to be opened and the mode
    // Ret. Val:  a pointer to the input stream
    // Pre:       file to be opened must exist           
    // Post:      
    //------------------------------------------------------------------------------
    
    Event inputEvent(FILE *inputStream);
    // Purpose:   To input a single event from the file
    // Arguments: the pointer to the input stream
    // Ret. Val:  an event structure
    // Pre:       array to store the structure must be declared           
    // Post:      
    //------------------------------------------------------------------------------
    
    
    //------------------------------------------------------------------------------
    //main
    int main(int argc, char *argv[]) {
        FILE *inputStream; // creates file pointer
        Event events[ARRAY_LENGTH]; //array to store events
        int arrayIndex = 0; // index for array of dates
    	Event tempEvent;// to store event temporarily for swap
    	int i,j; // counters
       
        
         //check for correct number of args
        if (argc < 2 ) {
                 printf("USAGE: %s <file to get events from> \n", argv[0]);
                 exit(1);
        }
     
        inputStream = safeOpen(argv[1], "r");// assign file to inputstream
        
        // store events into array until EOF is reached
        while (!feof(inputStream)) {
               events[arrayIndex] = inputEvent(inputStream);
               arrayIndex++;
               fscanf(inputStream, " ");
              
            }// end of while loop
       
        // bubble sort algorithm
        for (i=0; i < ARRAY_LENGTH; i++) { 
            
            for (j=0; j < ARRAY_LENGTH; j++) {
                if (((events[j].date.month) > (events[j+1].date.month)) ||
                   ((events[j].date.month) == (events[j+1].date.month)) &&
                   ((events[j].date.day) > (events[j+1].date.day))) {
                   tempEvent = events[j];
                   events[j] = events[j+1];
                   events[j+1] = tempEvent;
                } // end of if
                
            } //end of inner j for loop
        
        } // end of outer i loop
        
        
    
    
        // output the array of structures
        for (i=0; i < ARRAY_LENGTH; i++) {
              if (events[i].type == Anniversary) {
                      printf("Anniversary: ");
              }
        
              else if (events[i].type == Birthday) {
                   printf("Birthday: ");
              }
        
              printf("%i ", events[i].date.day);
              printf("%s\n", MONTHS[events[i].date.month-1]);
              printf(" - %s\n\n", events[i].description);
        }// end of for loop
        
    // Close the file
    	fclose(inputStream);
    	
    }  
    
        
    //------------------------------------------------------------------------------    
    // function to safely open a file and check for success
        FILE *safeOpen(char *fileName, char *mode){
        FILE *stream; // creates file pointer
             
             stream = fopen(fileName, "r"); // attach file to stream
        
        // check for open file success
        if (stream == NULL){
           printf("Error test opening file");
           exit(2);
        }
        return stream; // return inputStream pointer
    }// end of function
    //------------------------------------------------------------------------------
    
    //------------------------------------------------------------------------------
    //function to input data from file into structure
    Event inputEvent(FILE *inputStream) {
          Event tempEvent;// variable to store the data from file
          int type=0;// variable to store the event type
          
          fscanf(inputStream,"%i ", &type);
          
          // switch to set the enumerated type
          switch (type == 0) {
                 case true:
                     tempEvent.type = Birthday;
                 break;
                 
                 case false:
                      tempEvent.type = Anniversary;
                 break;
          } // end of switch
          
          fscanf(inputStream, "%i ", &tempEvent.date.day);
          fscanf(inputStream, "%i ", &tempEvent.date.month);
          fscanf(inputStream, "%[^\n]", tempEvent.description);
          
          return tempEvent;// return structure 
          
    }// end of function

  2. #2
    Registered User valaris's Avatar
    Join Date
    Jun 2008
    Location
    RING 0
    Posts
    507
    safeOpen() - I dont see definition for this. But if you are opening an empty file ie creating a file...
    Pre: file to be opened must exist

  3. #3
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    And if you're debugging it, at what point is the access violation raised?

  4. #4
    Registered User
    Join Date
    Jan 2008
    Posts
    15
    the empty file exist already exists, I will try and see where the access violation occurs

  5. #5
    Registered User
    Join Date
    Sep 2008
    Location
    Toronto, Canada
    Posts
    1,834
    Your fscanf(inputStream,"&#37;i ", &type); probably fails but you didn't check for that. Also, are you sure you should be using %i ?
    Your switch statement is questionable. true and false are defined someplace?

  6. #6
    Registered User
    Join Date
    Jan 2008
    Posts
    15
    I am unable to see exactly where the violation occurs (using DEV c++). The thing is the program works perfectly with a test file with the data that I provided earlier, so the switch statement works fine. I thought that true and false where predefined constants. The switch statement works as it should do, even though it may be questionable. the program reads in the first digit from the first line of the file and stored it in the structure member TYPE and if it a 0 then the enumerated type is set to birthday and if the first digit is a 1 then the enumerated type is set to anniversary.

    Any other ideas guys ?.......ill prob send it to my lecturer and get his advice as well.

  7. #7
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    true and false are defined in <stdbool.h>; since that's not there, it's probably being compiled in C++ mode. But yes, reading from an empty file might do bad things. And don't put spaces after your format specifiers when you're scanf'ing either.

  8. #8
    Registered User
    Join Date
    Oct 2008
    Location
    TX
    Posts
    2,059
    Quote Originally Posted by trevordunstan View Post
    Code:
        // bubble sort algorithm
        for (i=0; i < ARRAY_LENGTH; i++) { 
            
            for (j=0; j < ARRAY_LENGTH; j++) {
                if (((events[j].date.month) > (events[j+1].date.month)) ||
                   ((events[j].date.month) == (events[j+1].date.month)) &&
                   ((events[j].date.day) > (events[j+1].date.day))) {
                   tempEvent = events[j];
                   events[j] = events[j+1];
                   events[j+1] = tempEvent;
                } // end of if
                
            } //end of inner j for loop
        
        } // end of outer i loop
    In this bubble sort the i counter is not utilized at all and perhaps the events[] array is going out of bounds raising the segmentation violation.
    The error checking is in this code is quite sparse. Check for errors after each function call so the next time it'll be easier to pinpoint the problem when it happens.

  9. #9
    Registered User
    Join Date
    Jan 2008
    Posts
    15
    ok guys thanks for the info, ill have a bit of a closer look at it and see what I come up with, The bubble sort algorithm I got out of my study book, but yeh I can see now that the counter is not being used.

    Cheers for the help

  10. #10
    Registered User
    Join Date
    Jan 2008
    Posts
    15
    Hey guys,
    thought I would get back to the forum to show the solutions that I came up with in case other people have similar problems. The problem that I was having with the empty file was because I was not actually testing for the empty file before I processed it so i added this code
    Code:
    if (fscanf(inputStream,"%s", storeEOF) == EOF) {
           exit(2);
        }
    and another problem that I discovered it that DJGPP would compile but not run the program due to memory problems. This was because my bubble sort algorithm was not quite correct. originally I had this:

    Code:
    / bubble sort algorithm
        for (i=0; i < ARRAY_LENGTH; i++) { 
            
            for (j=0; j < ARRAY_LENGTH; j++) {
                if (((events[j].date.month) > (events[j+1].date.month)) ||
                   ((events[j].date.month) == (events[j+1].date.month)) &&
                   ((events[j].date.day) > (events[j+1].date.day))) {
                   tempEvent = events[j];
                   events[j] = events[j+1];
                   events[j+1] = tempEvent;
                } // end of if
                
            } //end of inner j for loop
        
        } // end of outer i loop
    So i changed it to this

    Code:
    for (i=0; i < numEvents-1; i++) {
        
            for (j=0; j < numEvents-1; j++) {
                      if (((events[j].date.month) > (events[j+1].date.month)) ||
                      ((events[j].date.month) == (events[j+1].date.month)) &&
                      ((events[j].date.day) > (events[j+1].date.day))) {
                           tempEvent = events[j];
                           events[j] = events[j+1];
                           events[j+1] = tempEvent;
                      } // end of if
                
            } //end of inner j for loop
        } // end of outer i for loop
    it seemed that the bubble sort was running off the end of the array. I had declared and array of ARRAY_SIZE and was looping through this array instead I should have been looping through ARRAY_SIZE-1

  11. #11
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,656
    > while (!feof(inputStream))
    See the FAQ.

    And yes, checking your return results would be a good idea.
    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.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Formatting a text file...
    By dagorsul in forum C Programming
    Replies: 12
    Last Post: 05-02-2008, 03:53 AM
  2. checking if a file is empty
    By finkus in forum C++ Programming
    Replies: 6
    Last Post: 11-29-2005, 04:10 PM
  3. archive format
    By Nor in forum A Brief History of Cprogramming.com
    Replies: 0
    Last Post: 08-05-2003, 07:01 PM
  4. simulate Grep command in Unix using C
    By laxmi in forum C Programming
    Replies: 6
    Last Post: 05-10-2002, 04:10 PM