Kimple
Kimple

Reputation: 127

C++ program crashes at delete only when character array gets the input of "1000!"

I wrote a quick and dirty factorial program using the GMP library in C++, which allocates some memory for a character array. The program works fine for all input values that I've tested, except 1000.

I've tried different ways to allocate the memory, and different ways to deallocate it, but none have worked so far and almost always crash on 1000.

This is everything that happens between creating the character array and deleting it. factor is the calculated factorial and mpz_sizeinbase returns the number of digits in the number in the specified base. gmp_sprintf just transforms the number into the character array.

int count = mpz_sizeinbase(factor, 10);
    char* zeroes = new char[count];

    gmp_sprintf(zeroes, "%Zd", factor);

    printf("After conversion: %s\n", zeroes);

    int trailingzeroes = 0;
    for(int i = strlen(zeroes)-1; i > 0; i--){
        if(zeroes[i] == '0')
            trailingzeroes++;
        else
            break;
    }

    printf("Trailing zeroes: %i\n", trailingzeroes);


    delete [] zeroes;

When the input is 1000, meaning that I want to calculate 1000!, I get the error

double free or corruption (!prev)
Aborted

at delete []. All other inputs work, as far as I can tell. What could I be doing wrong?

Upvotes: 0

Views: 115

Answers (1)

Max Langhof
Max Langhof

Reputation: 23691

From the mpz_sizeinbase documentation: "The right amount of allocation is normally two more than the value returned by mpz_sizeinbase, one extra for a minus sign and one for the null-terminator." You probably don't have a negative factorial, but you are certainly not allocating enough space for including the terminating null character.

It would be instructive to check the return value of gmp_sprintf because it tells you how many characters it actually wrote. I would wager that in your case it returns count+1, which would mean it wrote past the end of the buffer (which is Undefined Behavior).

The fact that it sometimes might work is probably related to the fact that "the result will be either exact or 1 too big" (for bases other than 2). That and of course the unpredictable nature of UB.

Upvotes: 4

Related Questions