如何检查 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++,让你自己容易受到很多错误的影响,其中一些可能不会立即导致崩溃 - 这些可能是最难确定的。 .
在 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++,让你自己容易受到很多错误的影响,其中一些可能不会立即导致崩溃 - 这些可能是最难确定的。 .