Search code examples
cfactorial

Abort trap: 6 (Calculating a long number factorial)


I am following the following function to calculate factorials of big numbers link, and I would like to understand a bit more why some things are happening...

#include<stdio.h>
#define MAX 10000
void factorialof(int);
void multiply(int);
int length = 0;
int fact[MAX];

int main(){
    int num;
    int i;

    printf("Enter any integer number : ");
    scanf("%d",&num);
   
    fact[0]=1;

    factorialof(num);
   
    printf("Factorial is : ");
    for(i=length;i>=0;i--){
         printf("%d",fact[i]);
    }
    return 0;
}

void factorialof(int num){
    int i;
    for(i=2;i<=num;i++){
         multiply(i);
    }
}
void multiply(int num){
    long i,r=0;
    int arr[MAX];
    for(i=0;i<=length;i++){
                arr[i]=fact[i];
        }

    for(i=0;i<=length;i++){
         fact[i] = (arr[i]*num + r)%10;
         r = (arr[i]*num + r)/10;
         //printf("%d ",r);
    }
    if(r!=0){
         while(r!=0){
             fact[i]=r%10;
             r= r/10;
             i++;
         }
    }
    length = i-1;   
}

My questions are:

  1. What is the real meaning of the MAX constant? What does it mean if it's bigger or smaller?
  2. I have found out that if I have a MAX = 10000 (as in the example), I can calculate up to 3250! If I try with 3251! I get a 'Abort trap: 6' message. Why is that number? Where does it come from?
  3. Which would be the difference if I compile this code for a 32-bit machine with the flag -m32? Would it run he same as in 64-bit?

Thanks!


Solution

  • As Scott Hunter points out, MAX is the maximum number of elements in the fact and arr arrays, which means it's the maximum number of digits that can occur in the result before the program runs out of space.

    Note that the code only uses MAX in its array declarations. Nowhere does it use MAX to determine whether or not it's trying to read from or write to memory beyond the end of those arrays. This is a Bad Thing™. Your "Abort trap: 6" error is almost certainly occurring because trying to compute 3251! is doing exactly that: using a too-large index with arr and fact.

    To see the number of digits required for a given factorial, you can increase MAX (say, to 20,000) and replace the existing printf calls in main with something like this:

    printf("Factorial requires %d digits.\n", length + 1);
    

    Note that I use length + 1 because length isn't the number of digits by itself: rather, it's the index of the array position in fact that contains the most-significant digit of the result. If I try to compute 3251!, the output is:

    Factorial requires 10008 digits.
    

    This is eight digits more than you have available in fact with the default MAX value of 10,000. Once the program logic goes beyond the allocated space in the array, its behavior is undefined. You happen to be seeing the error "Abort trap: 6."

    Interestingly, here's the output when I try to compute 3250!:

    Factorial requires 10005 digits.
    

    That's still too many for the program to behave reliably when MAX is set to 10,000, so the fact that your program calculates 3250! successfully might be surprising, but that's the nature of undefined behavior: maybe your program will produce the correct result, maybe it will crash, maybe it will become self-aware and launch its missiles against the targets in Russia (because it knows that the Russian counterattack will eliminate its enemies over here). Coding like this is not a good idea. If your program requires more space than it has available in order to complete the calculation, it should stop and display an appropriate error message rather than trying to continue what it's doing.