我想将C模块封装到C ++类中。
在C实现中,有一个函数将指针指向静态const
const BIGNUM *BN_value_one(void)
{
static const BN_ULONG data_one = 1L;
static const BIGNUM const_one =
{ (BN_ULONG *)&data_one, 1, 1, 0, BN_FLG_STATIC_DATA };
return (&const_one);
}
我想让它成为一个类中的静态方法,析构函数执行一些释放操作
class BigNumber
{
struct deleter
{
void operator() (BIGNUM *it)
{
BN_free(it); // The freeing operation provided by origin C library
}
};
using BN_ptr = std::unique_ptr<BIGNUM, deleter>;
/* The OpenSSL BIGNUM pointer */
BN_ptr bn;
public:
BigNumber() : bn(BN_new(), ::BN_free) {}
BigNumber(BigNumber &&other) : bn(std::move(other.bn)) {}
BigNumber(const BigNumber &other) : bn(BN_new(), ::BN_free)
{
::BN_copy(bn.get(), other.bn.get());
}
BigNumber(BIGNUM *src) : bn(src, ::BN_free) {}
static const BigNumber one()
{
static const BigNumber o(const_cast<BIGNUM *>(::BN_value_one()));
return o;
}
}
由于one()
方法将unique_ptr
返回到BN_value_one
中的静态变量,因此在销毁返回值时会发生分段错误。
有没有办法避免这种破坏,或者更好的封装?
答案 0 :(得分:2)
当您使用openssl库时,您不必使用BN_free()
,因为您的代码从未使用BIGNUM
分配BN_new()
。有关详细说明,请参阅此manpage。
所以你不需要unique_ptr
也不需要删除。
编辑#1:
我看到您的班级也可以保留已分配的BIGNUM
值。因此,有两种方法可以区分已分配和未分配的BIGNUM
值。
unique_ptr
。BN_free()
的删除器。编辑#2:
现在您的代码更完整了。您可以编写一个附加构造函数,该构造函数接受指向使用自己的虚拟自由函数的const BIGNUM
的指针。如果使用此构造函数,则必须避免使用const_cast
。
BigNumber(const BIGNUM *src) : bn(src, ::BN_dummy_free) {}
虚拟自由应该是这样的:
void BN_dummy_free(BIGNUM *a) {}
这应该适用于您的代码,并且不会以分段错误结束。所以你可以选择已分配和未分配的BIGNUM。
此外,您应该注意复制构造函数,因为它始终使用BN_free()
。您应该复制使用过的删除函数,该函数可能是BN_dummy_free()
函数。