代码之家  ›  专栏  ›  技术社区  ›  Evan Teran Benoît

避免libgmp中的流产

  •  6
  • Evan Teran Benoît  · 技术社区  · 14 年前

    我有一些使用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;
    }
    

    结果:

    $ ./test 
    gmp: overflow in mpz type
    Aborted
    

    显然,生产的数量真的很大。是否有比中止更优雅地处理错误的方法。这是一个基于GUI的应用程序,它中止是处理这类问题最不理想的方法。

    3 回复  |  直到 14 年前
        1
  •  3
  •   caf    11 年前

    在应用程序中优雅地处理这些错误的最佳方法可能是派生一个助手进程来执行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;
    }
    
        2
  •  4
  •   Jack Kelly    14 年前

    根据中的代码,您似乎运气不好 mpz/realloc.c mpz/realloc2.c . 如果请求的内存太多,它只会执行以下操作:

    if (UNLIKELY (new_alloc > INT_MAX))
      {
        fprintf (stderr, "gmp: overflow in mpz type\n");
        abort ();
      }
    
        3
  •  1
  •   Community Egal    4 年前

    覆盖 abort() 具有 LD_PRELOAD

    What is the LD_PRELOAD trick?

    编辑: 为了使答案更加完整,我将答案的文本复制到这里:

    如果将ldu PRELOAD设置为共享对象的路径,则该文件将在加载任何其他库(包括C运行时)之前加载,libc.so公司). 因此,要使用特殊的malloc()实现运行ls,请执行以下操作:

    $ LD_PRELOAD=/path/to/my/malloc.so /bin/ls