Search code examples
c++gmp

Segmentation fault (core dumped) while using GMP Integers


I wrote a simple program in C++, using the gmp library, which prints out the modulus of numbers which's digits are composed of 1 (like 1, 11, 111, 1111, 11111, ...) and 2001; problem is when the program reaches 23 digits of 1, I get an error saying Segmantation fault(core dumped). Can you point out where the problem is ? Here is my code :

#include <iostream>
#include <stdio.h>
#include <string>
#include <gmpxx.h>

int main(int argc, char** args){

    mpz_t currNumber;
    mpz_init(currNumber);   
    mpz_set_str(currNumber, "1", 10);

    while(mpz_sizeinbase(currNumber, 10) < 24){
        char* digits =  mpz_get_str(nullptr, 10, currNumber);
        strcat(digits, "1");
        mpz_set_str(currNumber, digits, 10);
        digits = nullptr;


        mpz_t r;
        mpz_init(r);    
        mpz_set_str(r, "1", 20);

        mpz_t divisor;
        mpz_init(divisor);  
        mpz_set_str(divisor, "2001", 20);


        mpz_mmod(r, currNumber, divisor);

        std::cout << "====>" << currNumber << " mod(2001) = " << r << "\n\n\n";

        //Clean up
        mpz_clear(r);
        mpz_clear(divisor);     
    }

    std::cout << "Went until " << mpz_sizeinbase(currNumber, 10) << " digits !" << "\n";

    ///Clean up
    mpz_clear(currNumber);

    return 0;
}

Solution

  • First obvious bug is:

        char* digits =  mpz_get_str(nullptr, 10, currNumber);
        strcat(digits, "1");
    

    The buffer allocated by mpz_get_str does not reliably have room for you to concatenate one extra character onto its contents.

    I think you could use:

        char* digits =  mpz_get_str(nullptr, 10, currNumber);
        std::string more_digits = std::string(digits) + "1";
        free(digits);
        mpz_set_str(currNumber, more_digits.c_str(), 10);
    

    1) Since you are in C++, you should use std::string for most string operations and don't need to learn the obscurities of working with C strings.
    2) If I understand mpz_get_str correctly (despite never having used it myself) you need to free the buffer it allocated (as I did in this suggested code) to avoid a memory leak.