Thread: Segmentation fault (cygwin)

  1. #1
    Registered User
    Join Date
    Oct 2010
    Posts
    16

    Angry Segmentation fault (cygwin)

    I have ben working on this code for a stupid amount of time from stupid pickiness of C (sorry ima java lover :P)
    and finally I have hit a fault I cant fix through beating my head against the keyboard.

    Code:
    // File name: wordGame.c
    // Auther: Michael Crook, 31246473
    // Date: Friday, 8th October
    // Purpose: This program is designed to read in
    //  input from a user alowing the user to choose
    //  what list or if the wish to create their own
    //  list of words to spell. Once the game component
    //  starts the user will enter in the words from
    //  the list, after entering n lines the user
    //  will have a score given to them on how well
    //  they performed.
    
    // ### ModifyLists Menu IP STEP ###
    
    #include <stdio.h>
    #include <string.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #ifdef WINDOWS // will include approporiate directory system for the OS
        #include <direct.h>
        #define GetCurrentDir _getcwd
    #else
        #include <unistd.h>
        #define GetCurrentDir getcwd
    #endif
    
    	typedef struct{
                char str[1000];
    	}files;
    
    void clearBuffer(char *string, char *message)
    {
        char ch;
        int i;
        while ((ch = getchar()) != '\n');
    }
    
    int makeWrd(char *Directory) // will create the file at Directory if it doesn't exist
    {
        FILE *fp;
        if((fp = fopen(Directory, "r")) == NULL) // if wrdDir.wrd exists, it is not re-created
        {
            fp=fopen(Directory, "w"); // ONLY executed if wrdDir.wrd does not exist
        }
    }
    
    
    void Changefile(files *fileLine, char *directory, int cutoff)
    {
        FILE *fp;
        fp = fopen(directory, "w");
        int i;
        for(i = 0; i<cutoff; i++)
        {
            fprintf(fp, "%s\r\n", fileLine[i].str);
        }
        fclose(fp);
    }
    
    void editLine(char *directory)
    {
        char ch;
        int i, tmp;
        int input = 0;
        
        files line[1000];
    
        int sizeOfFiles = makeFileArray(line, directory);
    
        do{
            printf("Please enter the line you wish to change\n");
            for(i = 0; i<sizeOfFiles; i++)
            {
                if(line[i].str != NULL)
                {
                    printf("%d: %s\n", i, line[i].str);
                }
            }
            do{
                input = 0;
                if(i == 0)
                {
                    printf("0: create new line and word\nEnter line number: ");
                }
                else
                {
                    printf("%d: create new line and word\nEnter line number: ", i);
                }
                fflush(stdin); // buffer wasn't empty, causing input issues
                scanf("%d%*c", &input);
            }while(input>i || input < 0);
            printf("Please enter the new word for line %d: ", input);
            scanf("%10[0-9a-zA-Z ]s%*c", line[input].str); // to accept " " in string
            sizeOfFiles++;
            Changefile(line, directory, sizeOfFiles);
            clearBuffer(line[input].str, "Success, please press <ENTER>");
        }while(booleanInput("Quit the line edditing", "continue Line editing", "Quit", "Continue"));
    }
    
    int makeFileArray(files *line, char *tmpDir)
    {
        FILE *fp;
        fp = fopen(tmpDir, "r");
        int i = 0;
        char lineStr[250];
    
        while(fscanf(fp, "%s", lineStr) != EOF) // while we are not EOF wrdDir.wrd put the line into lineStr and...
        {
            strcpy(line[i].str, lineStr); // coppies the value of lineStr into line[i].str
            i++;
        }
        fclose(fp);
        return(i);
    }
    
    int crtFle(char *fileName, char *directory)
    {
        FILE *fp;
        int success = 1, i, size;
        char tmpDir[FILENAME_MAX], tmpDir2[FILENAME_MAX];
        files line[1000];
    
        strcpy(tmpDir, directory);
        strcat(tmpDir, "wrdDir.wrd");
        makeWrd(tmpDir);
        fp = fopen(tmpDir, "w");
        fprintf(fp, "%s\r\n", "wrdDir.wrd");
        fclose(fp);
    
        size = makeFileArray(line, tmpDir);
    
        for(i = 0; i<size; i++)
        {
            if(strcasecmp(line[i].str, fileName) == 0)
            {
                success = 0;
            }
        }
        if(success == 1)
        {
            strcpy(tmpDir2, directory);
            strcat(tmpDir2, fileName);
            strcpy(line[size].str, fileName);
            Changefile(line, tmpDir, (size+1));
            makeWrd(tmpDir2);
            editLine(tmpDir2);
        }
    
        return(success);
    }
    
    
    void modifyLists(char *directory)
    
    {
        FILE *fp; // file managemnet system
        char fileName[250]; // used to store users selected .wrd file
        char lsDirectory[FILENAME_MAX]; // stores files located in the list file
        int i = 0, n = 0;
    
        do{
            if(booleanInput("edit another list", "create new list", "edit", "new"))
            {
                i = 1;
                do{
                    if(i == 0)
                    {
                        printf("Please enter a new file name\n");
                    }
                    printf("Please enter file name: ");
                    scanf("%10[0-9a-zA-Z ]s%*c", fileName);
                    strcat(fileName, ".wrd");
                    i = crtFle(fileName, directory);
                }while(i == 0);
            }
            else
            {
                strcpy(lsDirectory, directory); // directory MUST be keeped in tact, use lsDirectory for tmp directories
                strcat(lsDirectory, "wrdDir.wrd"); // creats "/lsDirectory/wrdDir.wrd"
                makeWrd(lsDirectory);
    
                int retry = 1; // declaired in if statement as it is not a necisary variable for TRUE
                char lineStr[250]; // temporarly holds each line in wrdDir.wrd
    
    
                files line[1000]; // holds the data in wrdDir.wrd
                printf("Please enter one of the following files\n(if you have imported a file, it will not show up, enter it in and it will still work)\n");
                while(fscanf(fp, "%s", lineStr) != EOF) // while we are not EOF wrdDir.wrd put the line into lineStr and...
                {
                    strcpy(line[i].str, lineStr); // coppies the value of lineStr into line[i].str
                    i++;
                    printf("%s\n", lineStr);
                }
    
    
                printf("File Name(*.wrd): "); // .wrd is not necisary, but it is the format of the program
                scanf("%s%*c", &fileName);
                do{
                    n++; // later on, if n != i, the list wont be added to the wrdDir.wrd
                }while((line[(n-1)].str != fileName) && n<i);
    
                fclose(fp);
    
    
    
                strcpy(lsDirectory, directory); // resets lsDirectory, so instead of holding the ls file location it can be used for the filename
                strcat(lsDirectory, fileName); // creates "/lsDirectory/fileName"
                if((fp = fopen(lsDirectory, "r")) == NULL) // checks if file exists
                {
                    fclose(fp);
                    printf("The file does not exist, Please try again.\n");
                }
                else // FILE EXISTS
                {
                    fclose(fp);
                    if(i == n && line[(n-1)].str != fileName) // if i = n and the last item in line.str != fileName
                    {
    
                        strcpy(line[(i)].str, fileName); // adds fileName to the end of the line[(i)] array
    
                        strcpy(lsDirectory, directory); // resets lsDirectory, to once again be used to hold data about the files in the directory
                        strcat(lsDirectory, "wrdDir.wrd"); // creates "/lsDirectory/wrdDir.wrd"
    
                        fp = fopen(lsDirectory, "w");
                        for(i = 0; i<=n; i++)
                        {
                            fprintf(fp, "%s\r\n", line[i].str); // re-writes the file with the new .wrd list at the end
                        }
                    }
                    fclose(fp);
                 //   lineEditor(lsDirectory);
                     retry = 0;
                }
    
    
            }
        }while(booleanInput("Quit the list edditing", "continue List editing", "Quit", "Continue"));
    }
    
    // Requires input in following format String(option 0 full), String(option 1 full), String(option 0 short), String(option 1 short)
    // returns if 1 or 0 was chosen
    int booleanInput(char lngOption0[25], char lngOption1[25], char shrtOption0[25], char shrtOption1[25]) //
    {
        int input, exitLoop = 0;
    
        do{
            printf("Would you like to %s or %s?\n", lngOption0, lngOption1);
            printf("[0] for %s\n", shrtOption0);
            printf("[1] for %s\n", shrtOption1);
            scanf("%d%*c", &input);
            if(input == 1 || input == 0)
            {
                exitLoop = 1;
            }
            else
            {
                printf("Pleaes enter a valid option\n");
            }
        }while(exitLoop == 0);
        return(input);
    }
    
    void setupFolder(char folderName[FILENAME_MAX], char *directory) // sets up a folder located in <direcotry> called <folderName> (/ / is needed, e.g, /tst/)
    {
        strcat(directory, folderName); // gets the directory which the .exe is located and adds the new folder name to the end
        mkdir(directory, S_IRWXU); // creates new directory with read, write, execute/search by owner permision
        return;
    }
    
    int main()
    {
        int tmp;
        char directory[FILENAME_MAX], userName[50]; // creates a char array big enough to hold this biggest directory string
        //getcwd(directory, sizeof(directory)); // will put the directory name into directory (cuts of stream at FILENAME_MAX)
        strcpy(directory, "/cygdrive/f/106/assignment");
        setupFolder("/lists/", directory); // creates a new folder inside directroy called "list"
    
        printf("Welcome to Word Game!!! Please enter your first name: ");
        scanf("%10[0-9a-zA-Z ]s%*c", userName);
        clearBuffer(userName, "Welcome to Word Game, Please press <ENTER>");
        
        do{
            if(booleanInput("play the Word Game", "open the list editor", "Play", "Editor"))
            {
                modifyLists(directory);
            }
            else
            {
                printf("0");
                //run game
            }
        }while(booleanInput("Quit the program", "Start the program again", "Quit", "Continue"));
        return;
    }
    
    
    /*
    
        FILE *fp; // file managemnet system
    
        char fileName[FILENAME_MAX];
    
        strcpy(fileName, "example.txt");
    
        strcat(directory, fileName);
        fp=fopen(directory, "w");
        fprintf(fp, "Testing...\n");
    
        fclose(fp);
    */
    The problem is a Segmentation fault (core dumped) which through using netbeans to debug (sigh I said I am a java lover :P what can I say, I like the cygwin debugger in netbeans)

    It happens in the function void editLine(char *directory)
    and I have found that this is what is causing the line
    Code:
    files line[1000];
    which is strange as it usualy doesn't cause this issue...
    when I start the program I enter my name, choose list editor (1), create a new list (1) then the fault happens... I have spent stupid ammounts of time on this assignment which I shouldn't have

  2. #2
    Registered User
    Join Date
    May 2010
    Posts
    4,632
    When I compiled your code I got several warning messages.

    main.c|69|warning: implicit declaration of function ‘makeFileArray’|
    main.c|98|warning: implicit declaration of function ‘booleanInput’|
    main.c|198|warning: format ‘%s’ expects type ‘char *’, but argument 2 has type ‘char (*)[250]’|
    main.c|294|warning: ‘return’ with no value, in function returning non-void|
    ||=== Build finished: 0 errors, 25 warnings ===|
    The other warnings are because I am compiling as C90 and probably will not affect your program.

    The first 2 warnings could be the cause of your problem. As they are in your editline() function.

    I would suggest that you prototype all functions either in an include file or at the top of main right after your includes.

    Jim

  3. #3
    Registered User
    Join Date
    Oct 2010
    Posts
    16
    Ima so fail this computer unit... whats prototyping again... I googled it and just about died of shock with the complexity wiki wants to describe it within Ive just spent the last 19 hrs working from scratch 2 a finished assignment in java with 1 7 hour (sleeping) break... so atm ima lil ........ed and cant think strait so I need it baby fed to me. sorry

  4. #4
    Registered User
    Join Date
    Oct 2010
    Posts
    16
    by the way... this has only been tested on a Cygwin environment, I attempted to make it Windows/mac/cygwin(linux) cross compatable, but I am still learnin so it aint guaranteed 2 work.

  5. #5
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    It's not bad code for a newbie, but still, it's a hell of a lot of code to dump on a forum without any clues.

    First, compile with debug (-g) and run in the debugger like so.
    Code:
    $ gcc -g foo.c
    $ gdb ./a.out 
    GNU gdb (GDB) 7.1-ubuntu
    Copyright (C) 2010 Free Software Foundation, Inc.
    License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
    This is free software: you are free to change and redistribute it.
    There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
    and "show warranty" for details.
    This GDB was configured as "i486-linux-gnu".
    For bug reporting instructions, please see:
    <http://www.gnu.org/software/gdb/bugs/>...
    Reading symbols from /home/sc/work/a.out...done.
    (gdb) run
    Starting program: /home/sc/work/a.out 
    
    Program received signal SIGSEGV, Segmentation fault.
    0x080483f5 in func (arr=0x80485c0) at foo.c:30
    30      *p = 0;
    (gdb) bt
    #0  0x080483f5 in func (arr=0x80485c0) at foo.c:30
    #1  0x0804847a in main () at foo.c:44
    The bt command is the backtrace, which shows you the function hierarchy at the point of failure. This will tell you at least where to start looking.

    > fflush(stdin);
    Use your clearbuffer function, it's MUCH better.

    > files line[1000];
    Do you know that this array is nearly 1MB in size?

    You have a very inconsistent view of how long these strings are supposed to be. In particular, many of your scanf calls seem to limit to 10 characters, but your typedef allows 1000 characters.
    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. segmentation fault... first time with unix...
    By theMethod in forum C Programming
    Replies: 16
    Last Post: 09-30-2008, 02:01 AM
  2. Segmentation fault
    By bennyandthejets in forum C++ Programming
    Replies: 7
    Last Post: 09-07-2005, 05:04 PM
  3. Segmentation fault
    By NoUse in forum C Programming
    Replies: 4
    Last Post: 03-26-2005, 03:29 PM
  4. Locating A Segmentation Fault
    By Stack Overflow in forum C Programming
    Replies: 12
    Last Post: 12-14-2004, 01:33 PM
  5. Segmentation fault...
    By alvifarooq in forum C++ Programming
    Replies: 14
    Last Post: 09-26-2004, 12:53 PM

Tags for this Thread