避免 libgmp 中的中止

发布于 2024-09-16 03:48:04 字数 515 浏览 5 评论 0原文

我有一些使用 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 的应用程序,它的中止几乎是处理此类问题的最不理想的方式。

I have some code that uses libgmp. At some point the user may request a factorial of a very large number. Unfortunately, this results in libgmp raising an abort signal.

For example the following code:

#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;
}

Results in:

$ ./test 
gmp: overflow in mpz type
Aborted

Apparently, the number produced is REALLY big. Is there anyway to handle the error more gracefully than an abort. This is a GUI based application and it aborting is pretty much the least desirable way to handle this sort of issue.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

你如我软肋 2024-09-23 03:48:04

根据 mpz/realloc.cmpz/realloc2 .c。如果请求了太多内存,它只会执行以下操作:

if (UNLIKELY (new_alloc > INT_MAX))
  {
    fprintf (stderr, "gmp: overflow in mpz type\n");
    abort ();
  }

It would appear that you are out of luck, based on the code in mpz/realloc.c and mpz/realloc2.c. If too much memory was requested, it just does this:

if (UNLIKELY (new_alloc > INT_MAX))
  {
    fprintf (stderr, "gmp: overflow in mpz type\n");
    abort ();
  }
灵芸 2024-09-23 03:48:04

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


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

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

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;
}

The best way to handle these errors gracefully in your application is probably to fork off a helper process to perform the GMP calculations. If the helper process is killed by SIGABRT, your parent process can detect that and report an error to the user.


(The below is my original answer, which has "undefined results" according to the GMP documentation - it is left here for completeness).

You can catch the error if you install a signal handler for SIGABRT that uses 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;
}
赤濁 2024-09-23 03:48:04

LD_PRELOAD 覆盖 abort()

LD_PRELOAD 技巧是什么?

编辑:为了使答案更加独立,我在此处复制该答案的文本:

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

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

感谢 JesperE。

Overwrite abort() with LD_PRELOAD.

What is the LD_PRELOAD trick?

Edit: To make the answer more self-contained, I copy the text of that answer here:

If you set LD_PRELOAD to the path of a shared object, that file will be loaded before any other library (including the C runtime, libc.so). So to run ls with a your special malloc() implementation, do this:

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

Credits to JesperE.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文