Thread: Segmentation fault, how come?

  1. #1
    Bit Fiddler
    Join Date
    Sep 2009
    Posts
    79

    Segmentation fault, how come?

    I'm new to C and have stumbled over a problem I can't get a grip of.

    I've written a function that reads floating point numbers from a file and put them in a allocated (malloc) match_t array. It works fine so far. But when writing a unit test for it (yes wrong order, I know), strange things happens.

    Code:
    typedef struct match_s {
    
        double home;
        double draw;
        double away;
    
    } match_t;
    Code:
    void test_readMatchStats() {
        
        int c;
        match_t *matchArray;
        match_t facit[] = {
            {0.11, 0.12, 0.13},
            {0.21, 0.22, 0.23},
            {0.31, 0.32, 0.33},
            {0.41, 0.42, 0.43},
            {0.51, 0.52, 0.53}
        };
        matchArray = readMatchStats("test.txt");
        ...
    }
    When the facit array gets over 4 in legth I get a segmentation fault, otherwise it works. If I comment out the call to readMatchStats, I can make it bigger. Why is that?

  2. #2
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    You might try allocating some memory for *matchArray;

  3. #3
    Bit Fiddler
    Join Date
    Sep 2009
    Posts
    79
    It is done in readMatchStats and matchArray recieves the address. That part works if I don't allocate the facit array, (longer than 4, that is).

  4. #4
    Registered User
    Join Date
    Sep 2004
    Location
    California
    Posts
    3,268
    There's not enough code to diagnose your problem. I don't even see how the facit array and the matchArray are related.
    bit∙hub [bit-huhb] n. A source and destination for information.

  5. #5
    Registered User
    Join Date
    Sep 2008
    Location
    Toronto, Canada
    Posts
    1,834
    We'd need to see the code for readMatchStats().

  6. #6
    Registered User hk_mp5kpdw's Avatar
    Join Date
    Jan 2002
    Location
    Northern Virginia/Washington DC Metropolitan Area
    Posts
    3,817
    Could be something in readMatchStats or another function called within the test_readMatchStats function that handles memory poorly. You may think it's working fine as long as the facit array has no more than 4 elements but the real problem lies elsewhere and you simply happen to get an error once you do put more than 4 elements into facit. Show the code for readMatchStats and any other of your functions called within test_readMatchStats... and probably the code for the rest of test_readMatchStats itself as well.
    "Owners of dogs will have noticed that, if you provide them with food and water and shelter and affection, they will think you are god. Whereas owners of cats are compelled to realize that, if you provide them with food and water and shelter and affection, they draw the conclusion that they are gods."
    -Christopher Hitchens

  7. #7
    Bit Fiddler
    Join Date
    Sep 2009
    Posts
    79
    Code:
    match_t *readMatchStats(char *fileName) {
    
        char *lineStart;
        int arrayIndex;
        int matchIndex;
        double *ptr;
        FILE *dataFile;
        char *token;
        char *line = alloca(sizeof(char) * READ_BUFFER_SIZE);
        match_t *matchArray = xmalloc(sizeof(match_t) * 13);
    
        dataFile = fopen(fileName, "r");
        
        while (fgets(line, READ_BUFFER_SIZE, dataFile) != NULL) {
            lineStart = strchr(line, ';');
            lineStart = lineStart == NULL ? line : lineStart + 1;
            charReplace(line, '#', '\0', 1);
            if (!strlen(lineStart)) continue;
            token = strtok(lineStart, " ");
            for (matchIndex = 0; matchIndex < 3; matchIndex ++) {
                if (!strIsFloat(token)) {
                    error(1, 0, "datafile parsing error -- expected float");
                }
                if (!matchIndex) ptr = &matchArray[arrayIndex].home;
                else if (matchIndex == 1) ptr = &matchArray[arrayIndex].draw;
                else ptr = &matchArray[arrayIndex].away;
    
                *ptr = strtod(token, NULL);
                token = strtok(NULL, " ");
            }
            
            arrayIndex ++;
        }
    
        fclose(dataFile);
    
        return matchArray;
        
    }
    Code:
    void test_readMatchStats() {
        
        int c;
        match_t *matchArray;
        match_t facit[] = {
            {0.11, 0.12, 0.13},
            {0.21, 0.22, 0.23},
            {0.31, 0.32, 0.33},
            {0.41, 0.42, 0.43},
            {0.51, 0.52, 0.53},
        };
        matchArray = readMatchStats("test.txt");
    
        /*for (c = 0; c < 13; c ++) {
            assert(facit[c].home == array[c].home);
            assert(facit[c].draw == array[c].draw);
            assert(facit[c].away == array[c].away);
        }*/
    
    }
    EDIT: (I forgot...)
    Code:
    void *xmalloc(size_t size) {
    
        void *ptr;
        
        if ((ptr = malloc(size)) == NULL) error(1, errno, NULL);
        
        return ptr;
    
    }
    Last edited by Fader_Berg; 08-30-2010 at 01:16 PM.

  8. #8
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    Quote Originally Posted by Fader_Berg View Post
    I've written a function that reads floating point numbers from a file and put them in a allocated (malloc) match_t array. It works fine so far. But when writing a unit test for it (yes wrong order, I know), strange things happens.
    That's only the wrong order if you were intending to do TDD.
    Writing unit tests when you think the code is ready is also fine. Sometimes the tests only come to you after you've written the code and you realise that you need to do something to force it down a certain code path during testing.
    TDD is definitely cool though.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  9. #9
    Registered User
    Join Date
    Dec 2007
    Posts
    2,675
    Code:
    match_t *matchArray = xmalloc(sizeof(match_t) * 13);
    What's this magic number 13 for?

    If you've got a segfault, compile in debug mode and run it in the debugger. When the fault happens examine the state of your program.

  10. #10
    Bit Fiddler
    Join Date
    Sep 2009
    Posts
    79
    Quote Originally Posted by rags_to_riches View Post
    Code:
    match_t *matchArray = xmalloc(sizeof(match_t) * 13);
    What's this magic number 13 for?
    For now, this function reads 13 matches (and/or 13 rows in the file), that's all. I'll deal with the flexibility later.

    EDIT: I haven't a clue, how to debug a program. Guess it's time to figure that out.
    Last edited by Fader_Berg; 08-30-2010 at 01:53 PM.

  11. #11
    Registered User hk_mp5kpdw's Avatar
    Join Date
    Jan 2002
    Location
    Northern Virginia/Washington DC Metropolitan Area
    Posts
    3,817
    Code:
    *ptr = strtod(token, NULL);
    Is NULL a valid value to be passing to the strtod function? That doesn't look right. A test in my IDE causes an abort when passing NULL.
    "Owners of dogs will have noticed that, if you provide them with food and water and shelter and affection, they will think you are god. Whereas owners of cats are compelled to realize that, if you provide them with food and water and shelter and affection, they draw the conclusion that they are gods."
    -Christopher Hitchens

  12. #12
    Registered User
    Join Date
    Jul 2007
    Posts
    131
    NULL is completely valid parameter for strtod. The standard even explains atof via call to strtod with NULL endptr.

  13. #13
    Bit Fiddler
    Join Date
    Sep 2009
    Posts
    79
    Quote Originally Posted by hk_mp5kpdw View Post
    Code:
    *ptr = strtod(token, NULL);
    Is NULL a valid value to be passing to the strtod function? That doesn't look right. A test in my IDE causes an abort when passing NULL.
    The documentation says so. But, the debugger points to that row too. On the other hand. If I don't allocate the facit array, it all works. I can print all values in the matchArray and they are all what they should be.
    If I give strtod the char **, it still seg faults, and the debugger points to ___strtod_l_internal () from /lib/libc.so.6

  14. #14
    Registered User
    Join Date
    Dec 2007
    Posts
    2,675
    How about initializing arrayIndex before you use it? You're writing who knows where here:
    Code:
    if (!matchIndex) ptr = &matchArray[arrayIndex].home;
                else if (matchIndex == 1) ptr = &matchArray[arrayIndex].draw;
                else ptr = &matchArray[arrayIndex].away;

  15. #15
    Bit Fiddler
    Join Date
    Sep 2009
    Posts
    79
    Thank you.

    It's easy to make mistakes and get blind on the same time, obviously. I'm spoiled with python and having the interpreter watching my back all the time.

    By the way... That piece of code there, really annoys me. Isn't there a way to something like...
    Code:
    (&matchArray[arrayIndex] + sizeof(double) * matchIndex) = strtod(token, NULL);
    ...instead? Writing directly to the value in the structure, without having ptr pointing to it.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 4
    Last Post: 04-20-2010, 10:55 PM
  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