如何检查 mpz_t 号码是否使用 GMP 初始化?

How to check if mpz_t number is initialized using GMP?

在 C++ 中使用 GMP 库。我有一个函数接收指向 mpz_t 数字的指针并从中设置另一个 gmp_z 数字。我需要一种方法来检查 *_amount 之前是否已经初始化。

void f(mpz_t* _amount)
{
    mpz_t amount;
    mpz_init(amount);

    if(!_amount){
        throw std::bad_alloc();
    }

    mpz_set(amount, *_amount);
}

如何检查 _amount 之前是否已初始化?

由于 _amount 是指针,因此您可以检查 null 或 void 以确保它是否已初始化。

谢谢

这是 C 中的不良做法 - 故事结束。您 检查_amount 是否已初始化。 GMP 库经过高度优化,确保正确初始化 mpz_t 对象是唯一正确的方法。因此,一个 mpz_t 对象可能 看起来 已初始化,但除非 mpz_init(_amount) 已被使用,否则这些字段可能是未初始化的垃圾。

如果已经设置了_amount也没关系。看看 mpz/set.c :

void
mpz_set (mpz_ptr w, mpz_srcptr u)
{
  mp_ptr wp, up;
  mp_size_t usize, size;

  usize = SIZ(u);
  size = ABS (usize);

  wp = MPZ_REALLOC (w, size);

  up = PTR(u);

  MPN_COPY (wp, up, size);
  SIZ(w) = usize;
}

显然,如果 mpz_t(参见:gmp-h.in)的字段未初始化,它们 可能 是垃圾。 mpz_set 可以在尚未分配的连续内存上执行 realloc。如果你幸运的话,那就是崩溃。如果不是,程序将以未定义状态继续。

mpz_t 视为 'C objects' 可能会有用。在初始化之前它们是无效的(并且不能正确使用)。我还要强调的是,当涉及到 GMP(多精度运算)的要求时,'overhead' 初始化一个变量(例如,为零)是绝对可以忽略不计的。

所以我们假设 _amount 已经正确初始化:


mpz_init(_amount); /* correctly sets mpz_t and assigns (0). */

/* (maybe `_amount` isn't (0)... that's OK too) */

void f (mpz_t *_amount)
{
    mpz_t amount;
    mpz_init(amount);

    /* unless using the GMP C++ interface, there's no definition
     * for the (!) operator. However `mpz_sgn` can be used here: */

    if (mpz_sgn(_amount) == 0) /* (_amount == 0 : exit condition?) */
    {
        mpz_clear(_amount); /* free space occupied by (_amount) */

        /* NOTE: this is NOT C++ with object unwinding! (amount) will
         * potentially leak resources! */

        mpz_clear(amount);
        throw std::bad_alloc {}; /* no leaks; deallocated storage. */
    }

    /* since (amount) will need to be deallocated, and we don't want
     * to deal with assignment errors - we simply 'swap' contents. */

    mpz_swap(_amount, amount); mpz_clear(amount);
}

我觉得你在这里混合范式。在本质上是 C 代码的地方使用 throw 会强制您手动清理,而 mpz_t 而不是 一个 C++ 对象 'constructs'默认,或在破坏/超出范围时释放所有资源。

您可能会发现 GMP C++ interface 更适合您的代码原型设计。 mpz_class 充当 C++ class,它在实例化时初始化,并在其作用域结束时调用它的析构函数。

现在你正在错误地混合 C/C++,让你自己容易受到很多错误的影响,其中一些可能不会立即导致崩溃 - 这些可能是最难确定的。 .