避免在libgmp中中止

Eva*_*ran 6 c c++ gmp

我有一些使用libgmp的代码.在某些时候,用户可以请求非常大数量的阶乘.不幸的是,这导致libgmp引发中止信号.

例如,以下代码:

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

int main() {

    mpz_t result;
    mpz_init(result);

    mpz_fac_ui(result, 20922789888000);

    std::cout << mpz_get_si(result) << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

结果是:

$ ./test 
gmp: overflow in mpz type
Aborted
Run Code Online (Sandbox Code Playgroud)

显然,产生的数字真的很大.反正是否比中止更优雅地处理错误.这是一个基于GUI的应用程序,它中止是处理此类问题的最不可取的方法.

caf*_*caf 3

在应用程序中优雅地处理这些错误的最佳方法可能是分叉一个辅助进程来执行 GMP 计算。如果辅助进程被 杀死SIGABRT,您的父进程可以检测到并向用户报告错误。


(以下是我的原始答案,根据 GMP 文档,它具有“未定义的结果” - 为了完整起见,将其留在这里)。

SIGABRT如果您为其使用安装信号处理程序,则可以捕获该错误longjmp()

jmp_buf abort_jb;

void abort_handler(int x)
{
    longjmp(abort_jb, 1);
}

int dofac(unsigned long n)
{
    signal(SIGABRT, abort_handler);
    if (setjmp(abort_jb))
        goto error;

    mpz_t result;
    mpz_init(result);

    mpz_fac_ui(result, 20922789888000);

    std::cout << mpz_get_si(result) << std::endl;

    signal(SIGABRT, SIG_DFL);
    return 0;

    error:
    signal(SIGABRT, SIG_DFL);
    std::cerr << "Caught SIGABRT from GMP.\n";
    return 1;
}
Run Code Online (Sandbox Code Playgroud)

  • -1 这个答案会调用未定义的行为(至少在 GMP 5.0.4 中)。引用[此处](http://gmplib.org/manual/Custom-Allocation.html#Custom-Allocation):`目前没有定义的方法让分配函数从内存不足等错误中恢复,它们必须终止程序执行。longjmp 或抛出 C++ 异常将产生未定义的结果。这在未来可能会改变。 (3认同)