c++ GMP mpz_init() causes Segmentation Fault 11

2.2k views Asked by At

I have a program that receives a Segmentation Fault 11 notice the simplicity of the main. Here is my entire working script:

#include <iostream>
#include "gmp.h"

void 
makeprime ()
{
    // *********************** VARIABLE DECLARATION *********************** //
    // initilize the variables as gmp class instances
    mpz_t l, rand;
    unsigned long seed;
    // perform inits to create variable pointers with 0 value
    mpz_inits(l, rand);
    //mpz_init(rand);

    // calculate the random number floor
    mpz_ui_pow_ui(l, 2, 199);

    // initilze the state object for the random generator functions
    gmp_randstate_t rstate;
    // initialize state for a Mersenne Twister algorithm. This algorithm is fast and has good randomness properties.
    gmp_randinit_mt(rstate);

    // create the generator seed for the random engine to reference 
    gmp_randseed_ui(rstate, seed);

    /*
    Function:
    int mpz_probab_prime_p (const mpz_t n, int reps)

    Determine whether n is prime. Return 2 if n is definitely prime, return 1 if n is probably prime (without being certain), 
    or return 0 if n is definitely composite.
    */
    do {
        // return a uniformly distributed random number in the range 0 to n-1, inclusive.
        mpz_urandomb(rand, rstate, 310);

        // add the random number to the low number, which will make sure the random number is between the low and high ranges
        mpz_add(rand, rand, l);

        gmp_printf("randomly generated number: %Zd\n", rand);

    } while ( !(mpz_probab_prime_p(rand, 25)) );        

    // *********************** GARBAGE COLLECTION *********************** //
    // empty the memory location for the random generator state
    gmp_randclear(rstate);
    // clear the memory locations for the variables used to avoid leaks
    mpz_clear(l);
    mpz_clear(rand);
}

int
main (void)
{
    makeprime();
    return 0;
}

Ok, now I'll add the following 2 lines at the beginning of main (not changing ANYTHING else about the script):

int
main (void)
{
    mpz_t r;      //added this line
    mpz_init (r); //and added this line

    makeprime();
    return 0; 
}

Now my program doesn't execute properly nor does it print or execute makeprime(), instead I get a Segmentation Fault 11 notice.

What gives? What am I doing wrong here?

1

There are 1 answers

7
lakshayg On BEST ANSWER

I was trying to debug your code using gdb and it gave me a segfault at line mpz_inits(l, rand). Then I modified that line and now it does not give a segfault. I will see if I can find a reason for the segfault.

#include <iostream>
#include "gmp.h"

void 
makeprime ()
{
    // *********************** VARIABLE DECLARATION *********************** //
    // initilize the variables as gmp class instances
    mpz_t l, rand;
    unsigned long seed;
    // perform inits to create variable pointers with 0 value

    //mpz_inits(l, rand);
    mpz_init(rand);
    mpz_init(l);

    // calculate the random number floor
    mpz_ui_pow_ui(l, 2, 199);

    // initilze the state object for the random generator functions
    gmp_randstate_t rstate;
    // initialize state for a Mersenne Twister algorithm. This algorithm is fast and has good randomness properties.
    gmp_randinit_mt(rstate);

    // create the generator seed for the random engine to reference 
    gmp_randseed_ui(rstate, seed);

    /*
    Function:
    int mpz_probab_prime_p (const mpz_t n, int reps)

    Determine whether n is prime. Return 2 if n is definitely prime, return 1 if n is probably prime (without being certain), 
    or return 0 if n is definitely composite.
    */
    do {
        // return a uniformly distributed random number in the range 0 to n-1, inclusive.
        mpz_urandomb(rand, rstate, 310);

        // add the random number to the low number, which will make sure the random number is between the low and high ranges
        mpz_add(rand, rand, l);

        gmp_printf("randomly generated number: %Zd\n", rand);

    } while ( !(mpz_probab_prime_p(rand, 25)) );        

    // *********************** GARBAGE COLLECTION *********************** //
    // empty the memory location for the random generator state
    gmp_randclear(rstate);
    // clear the memory locations for the variables used to avoid leaks
    mpz_clear(l);
    mpz_clear(rand);
}

int
main (void)
{
    makeprime();
    return 0;
}

EDIT:

I looked at the GMP Documentation and it says the following about mpz_inits.

— Function: void mpz_init (mpz_t x)

Initialize x, and set its value to 0.

— Function: void mpz_inits (mpz_t x, ...)

Initialize a NULL-terminated list of mpz_t variables, and set their values to 0.

You must end the list of variables you want to initialize with NULL. So you need to replace mpz_inits(l, rand) with mpz_inits(l, rand, NULL) and it works just fine.

EDIT:

You forgot to initialize the seed. In the function makeprime you declare unsigned long seed; but do not assign a value to the seed hence you get the same numbers every time because the value of the seed is same for every execution.

Typically random seeds are initialized using the system time. You can use

seed = (int) time(NULL);

to initialize the seed just after the declaration. Everything works fine then (Don't forget to include ctime or time.h).