Thread: Please Help! Segfaults and crashes!

  1. #1
    Registered User
    Join Date
    Oct 2013
    Posts
    29

    Please Help! Segfaults and crashes!

    When I go to run the Fibonacci function ( fib ), it begins to return incorrect calculations towards the higher numbers, but then seems to correct itself for a little bit, but then does it again and ultimately crashes. And the program seems to be crashing at random numbers. Sometimes the it will make it up to F(55), other times it will only get to F(20). Could someone please tell me why this is happening and/or how I could possibly fix this problem?

    Also, when I go to run the program on a Linux server, it segfaults, but it doesn't when I just run it on my IDE. Could you please tell me what could be causing this problem as well? Any help would be greatly appreciated.

    Note: the function adds two arrays with individual digits together. It does this to allow the program to add numbers that would exceed the boundaries of INT_MAX.

    Here is the header file "Fibonacci.h":
    Code:
    #ifndef __FIBONACCI_H
    #define __FIBONACCI_H
    typedef struct HugeInteger
    {
     // a dynamically allocated array to hold the digits of a huge integer
     int *digits;
     // the number of digits in the huge integer (approx. equal to array length)
     int length;
    } HugeInteger;
    
    // Functional Prototypes
    HugeInteger *hugeAdd(HugeInteger *p, HugeInteger *q);
    HugeInteger *hugeDestroyer(HugeInteger *p);
    HugeInteger *parseString(char *str);
    HugeInteger *parseInt(unsigned int n);
    unsigned int *toUnsignedInt(HugeInteger *p);
    HugeInteger *fib(int n);
    
    #endif

    And here is the function definitions w/ the main function attached
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <limits.h>
    #include <string.h>
    #include "Fibonacci.h"
    //create function for hugeAdd
    HugeInteger *hugeAdd(HugeInteger *p, HugeInteger *q){
    int i;
    //return NULL if either pointer is NULL
    if(p == NULL || q == NULL)
        return NULL;
    //create a new HugeInteger to store the result in
    HugeInteger *a = NULL;
    HugeInteger *trim = NULL;
    //dynamically allocate the structure
    a = malloc(sizeof(HugeInteger));
    trim = malloc(sizeof(HugeInteger));
    
    //check if malloc was successful
    if(a == NULL || trim == NULL){
        printf("\n23: Malloc failed\n");
        return NULL;
    }
    //set the arrays to NULL to confirm malloc worked
    a->digits = NULL;
    trim->digits = NULL;
    //if p is bigger than q
    if (p->length > q->length){
    //dynamically allocate the array
        a->digits = calloc(p->length+1, sizeof(int));
        a->length = p->length+1;
        //check to make sure calloc was successful
        if(a->digits == NULL){
            printf("\nCalloc failed\n");
            a->length = 0;
            free(a);
            return NULL;
        }
        //copy contents of the bigger array into the newly calloc'd array
        for (i=0; i<p->length; i++)
            a->digits[i] = p->digits[i];
    //add two arrays together
        for (i=0; i<q->length; i++){
            //if sum is >10 do this, since each cell should only hold 0-9
            if (p->digits[i]+q->digits[i]>=10){
                a->digits[i] += q->digits[i]-10;
                a->digits[i+1] += 1;
            }
            else{
                a->digits[i] += q->digits[i];
            }
        }
    }
    //if q is bigger than p
    else{
    
        a->digits = calloc(q->length+1, sizeof(int));
        a->length = q->length+1;
        //check to make sure calloc was successful
        if(a->digits == NULL){
            printf("\nCalloc Failed\n");
            a->length = 0;
            free(a);
            return NULL;
        }
         //copy contents of the bigger array into the newly calloc'd array
        for (i=0; i<q->length; i++)
            a->digits[i] = q->digits[i];
        //add two arrays together
        for (i=0; i<p->length; i++){
            //if sum is >10 do this, since each cell should only hold 0-9
            if (q->digits[i]+p->digits[i]>=10){
                a->digits[i] += p->digits[i]-10;
                a->digits[i+1] += 1;
            }
            else{
                a->digits[i] += p->digits[i];
            }
        }
    }
    //if there is a hanging 0 at the end
        if (a->digits[a->length-1] == 1)
            return a;
        else
        {
            trim->digits = malloc(sizeof(int)* (a->length-1));
            if(trim->digits == NULL)
            {
                printf("\ntrim malloc failed");
                free(trim);
                return NULL;
            }
            trim->length = a->length-1;
            //transfer digits over to new struct
            for (i=0; i<trim->length; i++)
            {
                trim->digits[i] = a->digits[i];
            }
            //clean up after yourself
            free(a->digits);
            a->length = 0;
            free(a);
        return trim;
        }
    }
    //create function for hugeDestroyer
    HugeInteger *hugeDestroyer(HugeInteger *p){
    int i;
    if (p == NULL)
        return NULL;
    free(p->digits);
    free(p);
    //set p to NULL and return NULL
    p = NULL;
    return NULL;
    }
    //create function for parseString
    HugeInteger *parseString(char *str){
    int i,j, k=0, temp=0;
    HugeInteger *a = NULL;
    HugeInteger *tempint = NULL;
    //check if we were passed a NULL string
    if (str == NULL)
        return NULL;
    //dynamically allocate the HugeIntegers
    a = malloc(sizeof(HugeInteger));
    a->digits = NULL;
    tempint = malloc(sizeof(HugeInteger));
    tempint->digits = NULL;
    //check if malloc worked
    if (a == NULL || tempint == NULL){
        printf("\nmalloc failed\n");
        return NULL;
    }
    //dynamically allocate a->digits, and set the length
    a->digits = malloc(sizeof(int)*(strlen(str)));
    a->length = strlen(str);
    //since tempint will store the same numbers as a in reverse later on, dynamically
    //allocate it the same way
    tempint->digits = malloc(sizeof(int)*(strlen(str)));
    tempint->length = strlen(str);
    //check if malloc worked
    if(a->digits == NULL){
        printf("\nMalloc failed\n");
        a->length = 0;
        free(a);
        return NULL;
    }
    
    //if "" is passed to function
    if(str == '\0'){
        a->digits[0] = 0;
        a->length = 1;
        return a;
    }
    //copy the numbers stored in str into the array in a
    for(i=0; i<strlen(str); i++)
        a->digits[i] = str[i] - '0';
    for(i=strlen(str)-1, j=0; i>=0; i--, j++)
    {
        tempint->digits[j] = a->digits[i];
    }
    for(i=0; i<strlen(str); i++)
        a->digits[i] = tempint->digits[i];
    //return a pointer to a
    return a;
    }
    //create function for parseInt
    HugeInteger *parseInt(unsigned int n){
    //declare variables
        HugeInteger *a = NULL;
        int mod = 10, counter=0, secondmod=1, i;
        unsigned int temp = n;
        a = malloc(sizeof(HugeInteger));
    //check to see if mallco failed
        if (a == NULL)
        {
            printf("\n174 malloc failed\n");
            return NULL;
        }
        //in the case of n being 0
        if (n == 0)
        {
            a->digits = NULL;
            a->digits = calloc(1, sizeof(int));
                //check if malloc succeeded
                if (a->digits == NULL)
                    return NULL;
            a->digits[0] = 0;
            a->length = 1;
            return a;
        }
        //determine how much digits make up the unsigned number
        while(temp>0)
        {
            temp/=10;
            counter++;
        }
        //check to see if malloc failed
        a->digits = NULL;
        a->digits = malloc(sizeof(int)*counter);
        if (a->digits == NULL)
        {
            printf("\nmalloc failed");
            free(a);
            return NULL;
        }
        //set the a->length originally to 0
        a->length = counter;
    
        //store every individual digit of the large number into a slot in the array
        for (i=0; i<a->length; i++)
        {
            a->digits[i] = (n % mod)/secondmod;
            mod*=10;
            secondmod*=10;
        }
        if (n == INT_MAX)
            a->digits[a->length-1] = 2;
        if (n == UINT_MAX)
            a->digits[a->length-1] = 4;
        return a;
    }
    //create function for toUnsignedInt
    unsigned int *toUnsignedInt(HugeInteger *p){
    //declare variables
        unsigned int *a=NULL, temp=0, currentuint=0, prevuint=0, n=UINT_MAX;
        int i, mod = 1;
    //return NULL if we were fed a NULL pointer or if malloc failed
        if (p == NULL)
            return NULL;
        if(a  == NULL)
        {
            printf("/ncalloc failed");
            return NULL;
        }
    
    temp = 0;
    //convert the number stored in p to an unsigned integer
    //(essentially undo what you did in parseInt)
        for(i=0; i<p->length; i++)
        {
            temp = temp + p->digits[i] * mod;
            mod *= 10;
            if (temp < prevuint)
                return NULL;
            prevuint = temp;
        }
    a = &temp;
    //return NULL if the unsigned integer we created exceeds UINT_MAX
    
    //return a pointer to the unsigned integer
    return a;
    }
    //create a function for fibonacci sequence
    HugeInteger *fib(int n){
    //Declare variables
        HugeInteger *a = NULL;
        HugeInteger *b = NULL;
        HugeInteger *c = NULL;
        int i,j,k;
    //allocate memory for the structure
        a = malloc(sizeof(HugeInteger));
        b = malloc(sizeof(HugeInteger));
        c = malloc(sizeof(HugeInteger));
    //check if malloc worked
        if (a == NULL || b == NULL)
        {
            printf("\nmalloc failed\n");
            return NULL;
        }
    //initialize the array pointer to NULL
        a->digits = NULL;
        b->digits = NULL;
        c->digits = NULL;
        
    //dynamically allocate memory for the arrays
        a->digits = malloc(sizeof(int));
        b->digits = malloc(sizeof(int));
        c->digits = malloc(sizeof(int));
    //if a's malloc failed
        if (a->digits == NULL)
        {
            printf("\nmalloc failed");
            free(a);
            return NULL;
        }
    //if b's malloc failed
        if (b->digits == NULL)
        {
            printf("\nmalloc failed");
            free(b);
            //since it passed the first if statement, we have to free a too
            free(a->digits);
            free(a);
            return NULL;
        }
    //if c's malloc failed
        if (c->digits == NULL)
        {
            printf("\nmalloc failed");
            free(c);
            free(b->digits);
            free(b);
            free(a->digits);
            free(a);
            return NULL;
        }
        //set length
        a->length = 1;
        b->length = 1;
    //set the base case
        a->digits[0] = 1;
        b->digits[0] = 0;
    //the bulk of the fibonacci function, which occurs if n>0
    if (n > 0)
    {
    //order n operation
        for (i = 1; i<=n; i++)
            {
                //add the two previous (or base cases) together. c = a+b
                c = hugeAdd(a,b);
                //a = b
                for (j=0; j<b->length; j++)
                    a->digits[j] = b->digits[j];
                    a->length = b->length;
                //b = c
                for (j=0; j<c->length; j++)
                    b->digits[j] = c->digits[j];
                    b->length = c->length;
            }
    }
        return b;
    }
    
    // print a HugeInteger (followed by a newline character)
    void hugePrint(HugeInteger *p)
    {
     int i;
     if (p == NULL || p->digits == NULL)
     {
      printf("(null pointer)\n");
      return;
     }
     for (i = p->length - 1; i >= 0; i--)
      printf("%d", p->digits[i]);
     printf("\n");
    }
    int main(void)
    {
     int i;
     HugeInteger *p;
     for (i = 0; i <= 1000; i++)
     {
      printf("F(%d) = ", i);
      hugePrint(p = fib(i));
      hugeDestroyer(p);
     }
     return 0;
    }

  2. #2
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    You're running it on Linux: why aren't you compiling with the -g flag and running it in gdb, so that gdb will tell you exactly what state everything is in when it crashes?

  3. #3
    Registered User
    Join Date
    Oct 2006
    Posts
    3,445
    if you're using a proper IDE like eclipse, code::blocks, or netbeans, you should be able to debug right from within the IDE. using a debugger (especially when integrated in an IDE) is pretty easy, and a good skill to know.
    What can this strange device be?
    When I touch it, it gives forth a sound
    It's got wires that vibrate and give music
    What can this thing be that I found?

  4. #4
    Registered User
    Join Date
    Oct 2013
    Posts
    29
    Quote Originally Posted by Elkvis View Post
    if you're using a proper IDE like eclipse, code::blocks, or netbeans, you should be able to debug right from within the IDE. using a debugger (especially when integrated in an IDE) is pretty easy, and a good skill to know.
    I'm not really sure how debuggers work or how to set up my program to support the debugger (I'm using codeblocks, but the option to run the debugger isn't clickable). From what I've found online, the debugger only works on projects, not on single files.

  5. #5
    Registered User
    Join Date
    Oct 2006
    Posts
    3,445
    I'd suggest that you create a project then, based on your source file.
    What can this strange device be?
    When I touch it, it gives forth a sound
    It's got wires that vibrate and give music
    What can this thing be that I found?

  6. #6
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    It's already been suggested you learn to use a debugger. Along with a debugger, look into using tools like electric fence and valgrind to help you find memory bugs.

    You also didn't take my advice about reducing duplicated code in one of your several other threads on the same exact program. Note, at least one bug I found in the code you posted in this thread is from a failure to combine duplicate code. You did the same thing 3 times, 2 times correctly and once incorrectly. If you combined all duplicate code into a single function, you would have one place to find and fix such bugs, saving you massive headaches like this. You also have lots of useless lines of code, setting values right before you free something, setting p to NULL in hugeDestroyer (that only sets the function's local copy), and doing things like returning a value from hugeDestroyer, which is pointless and you don't use the value anyway. I mentioned this before too.

    I suggest you stick with one thread from here on out since your questions are all very related. And you should actually take the advice you're given. We tend to lose interest in people who don't take the advice we give them.

    EDIT: I see you just asked for help using a debugger, which is a good first step in following our advice to use a debugger. Google is probably helpful here too: https://www.google.com/search?q=sett...use+a+debugger.

  7. #7
    Registered User
    Join Date
    Oct 2013
    Posts
    29
    Quote Originally Posted by anduril462 View Post
    It's already been suggested you learn to use a debugger. Along with a debugger, look into using tools like electric fence and valgrind to help you find memory bugs.

    You also didn't take my advice about reducing duplicated code in one of your several other threads on the same exact program. Note, at least one bug I found in the code you posted in this thread is from a failure to combine duplicate code. You did the same thing 3 times, 2 times correctly and once incorrectly. If you combined all duplicate code into a single function, you would have one place to find and fix such bugs, saving you massive headaches like this. You also have lots of useless lines of code, setting values right before you free something, setting p to NULL in hugeDestroyer (that only sets the function's local copy), and doing things like returning a value from hugeDestroyer, which is pointless and you don't use the value anyway. I mentioned this before too.

    I suggest you stick with one thread from here on out since your questions are all very related. And you should actually take the advice you're given. We tend to lose interest in people who don't take the advice we give them.

    EDIT: I see you just asked for help using a debugger, which is a good first step in following our advice to use a debugger. Google is probably helpful here too: https://www.google.com/search?q=sett...use+a+debugger.
    I thought I had gotten rid of the duplicated code. At least I thought I had changed what you suggested. I had thought when you said duplicated code that I had inadvertently done something, and then did it again a second time a couple lines down. Are you saying that I'm doing the same thing in three separate functions, and that I should just create an auxillary function to implement what it is that I have duplicated?

    And I have ran my project through the debugger several times, but other than informing me of a couple unused declarations, it didn't find anything wrong with the code, which is still crashing at random numbers.

    And I will definitely look into electric fence and valgrind. Thank you for those!

  8. #8
    Registered User
    Join Date
    Oct 2013
    Posts
    29
    And sorry to everyone for posting multiple threads about the project. I wasnt sure what the right thing to do was for multiple errors. Since I had resolved the issues I had been experiencing in the post, I wasn't sure if I should have posted questions about the other functions on there as well. I'll stick to one post from now on

  9. #9
    Registered User
    Join Date
    Oct 2013
    Posts
    29
    Also, do you know of any tools similar to electricfence or valgrind that would work on Windows? I have been testing my code on Linux via an emulator, but I'm writing the code on Windows 8

  10. #10
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    Quote Originally Posted by blackfox_1109 View Post
    I thought I had gotten rid of the duplicated code. At least I thought I had changed what you suggested. I had thought when you said duplicated code that I had inadvertently done something, and then did it again a second time a couple lines down. Are you saying that I'm doing the same thing in three separate functions, and that I should just create an auxillary function to implement what it is that I have duplicated?
    The latter is more what I was going for. Auxiliary functions are one way. You have the same malloc and null checks for creating a hugeInteger in a dozen or so places. Make that a function that takes the number of digits, and returns either a pointer to completely allocated struct with length set and digits initialized, or NULL on any failure (remembering to free the struct if calloc'ing the digits fails).

    Sometimes pulling common code out of an if/else block or switching around a few logical structures helps. Notice that lines 29-52 and 57-79 are virtually identical. That's a great example of where you can pull out common code. For example:
    Code:
    if (p->length > q->length) {
        50 lines of code doing something with p
    }
    else {
        The same 50 lines of code doing something with q
    }
    That is ~100 lines of code. Now, what if you did
    Code:
    if (p->length > q->length) {
        largest_addend = p
    }
    else {
        largest_addend = q
    }
    50 lines of code doing something with largest_addend
    Now you're down to just over 50 lines of code period. The line counts are off, but illustrate the point. All the complicated logic of adding the digits only happens once. One place to make, find and fix errors. One place to maintain the code.
    Quote Originally Posted by blackfox_1109 View Post
    And I have ran my project through the debugger several times, but other than informing me of a couple unused declarations, it didn't find anything wrong with the code, which is still crashing at random numbers.
    Unused variable warnings come from the compiler, not the debugger. Compiler warning and error messages are not the same thing. They happen before you run your program. A debugger is meant to be used while (or sometimes after) you run your program.
    Quote Originally Posted by blackfox_1109 View Post
    And I will definitely look into electric fence and valgrind. Thank you for those!
    They both are Linux specific, but you seem to have access to a Linux system. Google for the tool plus "windows alternative" or some such, if you really need Windows versions. Electric fence is simpler, but less powerful; valgrid is a lot more powerful but can be complicated (basic memory checks are pretty easy though).

  11. #11
    Registered User
    Join Date
    Oct 2013
    Posts
    29
    This piece of code produces an error only when run though Linux servers. My IDE and debuggers don't have a problem with it on my system. I don't know why it is causing the error. I have tried numerous times to change it to get it to work right, but nothing has been successful.

    Here is the error:
    Code:
    *** glib detected *** ./fib02.exe: free(): invalid pointer: 0xbfc5b59c ***

    Code:
    //create function for toUnsignedInt
    unsigned int *toUnsignedInt(HugeInteger *p){
    //declare variables
        unsigned int *a=NULL, temp=0, mod = 1, prevuint=0;
        int i;
    //return NULL if we were fed a NULL pointer or if malloc failed
        if (p == NULL)
            return NULL;
    //convert the number stored in p to an unsigned integer
    //(essentially undo what you did in parseInt)
        for(i=0; i<p->length; i++)
        {
            temp = temp + p->digits[i] * mod;
            mod *= 10;
            if (temp < prevuint)
                return NULL;
            prevuint = temp;
        }
    a = &temp;
    //return a pointer to the unsigned integer
    return a;
    }
    This part of the code fails when the main function attempts to free the pointer. Can someone please explain why this is doing so or what I can do to prevent this problem?



    Here is the test case that it runs through that crashes on the Linux server:

    Code:
    // print a HugeInteger (followed by a newline character)
    void hugePrint(HugeInteger *p)
    {
     int i;
     if (p == NULL || p->digits == NULL)
     {
      printf("(null pointer)\n");
      return;
     }
     for (i = p->length - 1; i >= 0; i--)
      printf("%d", p->digits[i]);
     printf("\n");
    }
    int main(void)
    {
     unsigned int *temp;
     HugeInteger *p;
     hugePrint(p = parseString("12345"));
     printf("%u\n", *(temp = toUnsignedInt(p)));
     free(temp);
     hugeDestroyer(p);
     hugePrint(p = parseString("354913546879519843519843548943513179"));
     temp = toUnsignedInt(p);
     if (temp == NULL)
      printf("Good work.\n");
     else
      printf("Uh oh...\n");
     free(temp);
     hugeDestroyer(p);
     hugePrint(p = parseString(NULL));
     temp = toUnsignedInt(p);
     if (temp == NULL)
      printf("Good work.\n");
     else
      printf("Uh oh...\n");
     free(temp);
     hugeDestroyer(p);
     hugePrint(p = parseInt(246810));
     printf("%u\n", *(temp = toUnsignedInt(p)));
     free(temp);
     hugeDestroyer(p);
     hugePrint(p = parseInt(0));
     printf("%u\n", *(temp = toUnsignedInt(p)));
     free(temp);
     hugeDestroyer(p);
     hugePrint(p = parseInt(INT_MAX));
     printf("%u\n", *(temp = toUnsignedInt(p)));
     free(temp);
     hugeDestroyer(p);
     hugePrint(p = parseInt(UINT_MAX));
     printf("%u\n", *(temp = toUnsignedInt(p)));
     free(temp);
     hugeDestroyer(p);
     return 0;
    }
    Note: it uses the parse string function mentioned in the top of this post, but that works perfectly. Also, the toUnsignedInt function also seems to work right, because it produces the correct output, but since the program crashes before it gets to destroyer, it has to be an issue with the freeing of the unsigned integer pointer. Any help with this issue would be greatly appreciated.

  12. #12
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    Quote Originally Posted by blackfox_1109 View Post
    This piece of code produces an error only when run though Linux servers. My IDE and debuggers don't have a problem with it on my system. I don't know why it is causing the error. I have tried numerous times to change it to get it to work right, but nothing has been successful.

    Here is the error:
    Code:
    *** glib detected *** ./fib02.exe: free(): invalid pointer: 0xbfc5b59c ***
    The fact that your IDE/debuggers "don't have a problem" doesn't mean much. Many bugs in memory handling result in undefined behavior which mean anything can happen. It may fail on one system but not another. It may only fail on some versions of Linux, or when compiled with certain compilers or certain versions of certain compilers. It may not compile at all, or it may compile fine once, and not compile 30 seconds later. It could reformat your compiler or catch your monitor on fire, though that is highly unlikely.

    That error suggests that you attempt to call free on a pointer that you never malloc'ed/calloc'ed/realloc'ed. This could happen from trying to pass, e.g. an array like char foo[10]; to free(), since the array was not allocated. More likely (in your case at least), is that you're passing free a "garbage" value -- either an uninitialized pointer, or a pointer that had a good value, but that got trampled because you have a memory bug like writing to an array out of bounds. I suspect an array out of bounds error. Make sure you always allocate enough digits when "assigning" hugeIntegers* and handling carries when adding the last digits.

    * Note, you only "assign" hugeIntegers in one or two places, by a simple assignment loop. Still, that is duplicated code that should be in a function. Consider:
    Code:
    void hugeAssign(hugeInteger *dest, hugeInteger *src)
    ...
    hugeAssign(a, b);  // assigns b to a, i.e. a = b;
    hugeAssign(b, c);  // see, much simpler
    I think you can glean what the function should do.

  13. #13
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    You return a pointer to a local variable in toUnsignedInt, which means this function has always been broken (regardless of Windows or Linux). You need to dynamically allocate that memory in toUnsignedInt.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. inexplicable segfaults
    By KBriggs in forum C Programming
    Replies: 10
    Last Post: 02-06-2014, 10:57 AM
  2. Segfaults - again
    By mike_g in forum C Programming
    Replies: 2
    Last Post: 07-20-2008, 12:49 PM
  3. copy() segfaults
    By Kaiser in forum C++ Programming
    Replies: 8
    Last Post: 09-29-2007, 06:17 PM
  4. Segfaults
    By mike_g in forum C Programming
    Replies: 3
    Last Post: 08-16-2007, 11:47 AM
  5. STRTOK SegFaults!
    By DarthKoRn in forum C Programming
    Replies: 3
    Last Post: 09-11-2005, 02:29 PM

Tags for this Thread