Swi prolog GMP-pow中的溢出处理

Swi prolog GMP-pow中的溢出处理,swi-prolog,yap,c,biginteger,gmp,Swi Prolog,Yap,C,Biginteger,Gmp,(我只是主要通过和间接使用GMP库。但我对解决此问题非常感兴趣。) 当使用大得离谱的值执行指数运算时,主机系统或GMP不再能够适当地处理溢出。我已经和上述系统的开发人员谈过了,但是他们没有看到一个简单的解决方案 其他GMP系统/用户是否知道该问题?您如何处理此类溢出 作为健全性检查,首先测试7^7^7的值,该值应为:375982…32343 例如,在32位系统上,查询?-X是13^1150000000。产生这样的溢出。以下是YAP给出的信息: GNU gdb (GDB) 7.0-ubuntu C

(我只是主要通过和间接使用GMP库。但我对解决此问题非常感兴趣。)

当使用大得离谱的值执行指数运算时,主机系统或GMP不再能够适当地处理溢出。我已经和上述系统的开发人员谈过了,但是他们没有看到一个简单的解决方案

其他GMP系统/用户是否知道该问题?您如何处理此类溢出

作为健全性检查,首先测试7^7^7的值,该值应为:375982…32343

例如,在32位系统上,查询
?-X是13^1150000000。
产生这样的溢出。以下是YAP给出的信息:

GNU gdb (GDB) 7.0-ubuntu Copyright (C) 2009 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "i486-linux-gnu". For bug reporting instructions, please see: ... Reading symbols from /opt/gupu/src/yap-6.3/narch-gupu2/yap...done. (gdb) run -f Starting program: /opt/gupu/src/yap-6.3/narch-gupu2/yap -f YAP 6.3.2 (i686-linux): Sun Nov 11 04:19:37 CET 2012 ?- X is 13^1150000000. Program received signal SIGSEGV, Segmentation fault. 0x001638d8 in ?? () from /usr/lib/libgmp.so.3 (gdb) bt #0 0x001638d8 in ?? () from /usr/lib/libgmp.so.3 #1 0x00164470 in __gmpn_mul_fft () from /usr/lib/libgmp.so.3 #2 0x001646c2 in __gmpn_mul_fft_full () from /usr/lib/libgmp.so.3 #3 0x00165f28 in __gmpn_sqr_n () from /usr/lib/libgmp.so.3 #4 0x0014b58b in __gmpz_n_pow_ui () from /usr/lib/libgmp.so.3 #5 0x0014c4a1 in __gmpz_pow_ui () from /usr/lib/libgmp.so.3 #6 0x080c4a1d in Yap_gmp_exp_int_int (i1=13, i2=1150000000) at ../C/gmp_support.c:939 #7 0x0815f9df in p_exp (t1=, t2=3082051592) at ../C/arith2.c:609 #8 0x080b1f19 in Eval (t=0) at ../C/eval.c:147 #9 0x080b2251 in p_is () at ../C/eval.c:186 #10 0x0806b56a in Yap_absmi (inp=0) at ../C/absmi.c:6912 #11 0x080b3655 in exec_absmi (top=) at ../C/exec.c:1002 #12 0x080b3b1f in do_goal (t=, CodeAdr=, arity=, pt=0x0, top=1) at ../C/exec.c:1068 #13 0x080b3d1d in Yap_RunTopGoal (t=135918154) at ../C/exec.c:1291 #14 0x08061a6f in YAP_RunGoalOnce (t=135918154) at ../C/c_interface.c:2511 #15 0x0805c2f5 in do_top_goal (argc=2, argv=0xbffff4c4) at ../console/yap.c:84 #16 exec_top_level (argc=2, argv=0xbffff4c4) at ../console/yap.c:131 #17 main (argc=2, argv=0xbffff4c4) at ../console/yap.c:172 (gdb) 但是,

?- X is 2^2^63.
ERROR: Out of global stack
?- X is 2^2^62.
gmp: overflow in mpz type
Abort
从下面开始:

?- X is 2^2^36.
ERROR: Out of global stack
?- X is 2^2^37.
gmp: overflow in mpz type
Abort

因此,如果数字足够大,则错误由SWI检测,因此可以由SWI处理(错误:消息由SWI处理)。

好吧,看来我运气不好:

fprintf(标准,“gmp:mpz类型中的溢出\n”); 中止(); 至少此溢出已被处理,不能用作攻击


任何使用GMP的系统如果没有这个问题,必须使用修改过的库或复制功能来估计大小。

13^1150000000大约是2^4255505675,需要4255505675位来表示。 每字节8位,这大约是500 MB的内存。 看起来应该合适


可能计算中涉及了几个临时变量,它超出了进程大小限制。

看起来,如果你有一个Cray,它会工作

#if defined (_CRAY) && ! defined (_CRAYMPP)
/* plain `int' is much faster (48 bits) */
#define __GMP_MP_SIZE_T_INT     1
typedef int         mp_size_t;
typedef int         mp_exp_t;
#else
#define __GMP_MP_SIZE_T_INT     0
typedef long int        mp_size_t;
typedef long int        mp_exp_t;
#endif

一些人为了解决这个问题而做的一些事情(不受支持,它会泄漏一些内存,但他们发现总比没有好):GMP允许您指定一个替换分配器(mp_set_memory_函数)。从这个分配器,你可以调用Maloc,如果失败,你可以抛出C++异常(如果你使用GCC,请重新编译GMP与-FExcExts)或调用LangJMP或类似的绕过GMP的失败处理并跳回你控制的代码。

< P>不是一个答案,而是SWI Prolog所做的解释。首先,它估计 可能发生溢流。如果确定,它将在调用GMP之前引发错误。否则, 依赖GMP分配挂钩并在失败时执行longjmp()。它记录了哪些 分配的是什么,并解除分配给已中止的GMP操作的内存。信息技术 可以这样做,因为内存永远不在GMP的控制之下。成功的结果 GMP计算被复制到Prolog堆栈,并接受Prolog内存管理

这在过去是有效的,但在最近的版本中不起作用。我怀疑GMP估计了这个尺寸 如果malloc()钩子知道这将失败,它甚至不需要调用它。我所需要的只是一种方法来确保钩子总是被调用,即使它的值大得离谱。任何大于size_t所能表示的大小的东西都可以用(size_t)-1来调用钩子


另外,由于复制到(较小的)Prolog运行时堆栈中,它溢出的时间远远早于内存可以存储的时间。

在最新版本中,它打印出消息并中止。以这种方式,应用程序无法处理溢出。在本例中,SWI序言可以肯定的是:我感兴趣的是得到一个干净的错误,它可以由SWI直接处理。如果你有一个SIGABRT的处理程序,这个进程将不会消亡。不幸的是,太粗糙:溢出通常由用户提供的malloc处理。除了这样的情况。一个可能的解决方案可能是要求(-1)多个字节或类似的。谢谢!需要消化一段时间:-)! fprintf (stderr, "gmp: overflow in mpz type\n"); abort ();
#if defined (_CRAY) && ! defined (_CRAYMPP)
/* plain `int' is much faster (48 bits) */
#define __GMP_MP_SIZE_T_INT     1
typedef int         mp_size_t;
typedef int         mp_exp_t;
#else
#define __GMP_MP_SIZE_T_INT     0
typedef long int        mp_size_t;
typedef long int        mp_exp_t;
#endif