简体   繁体   中英

How to refering a static variable in a class static member?

I'm tring to encapsulate a C module into C++ classes.

In the C implementation there is a function returing a pointer to a static 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);
}

I'm tring to make it a static method in a class with a destructor doing some releasing actions

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

Since the one() method returning a unique_ptr to a static variable in BN_value_one , it will occurs a segmentation fault when destructing the returned value.

Is there any way the avoid such destruction, or any better encapsulation?

As you're using the openssl library you don't have to use BN_free() because your code never allocated a BIGNUM with BN_new() . For more explanation see this manpage .

So you don't need the unique_ptr nor the deleter.

Edit #1:

I see that your class can also hold allocated BIGNUM values. So there are two possibilities to distinguish between allocated and not allocated BIGNUM values.

  1. Your BigNumber class could provide two different constructors. You can save the state of allocation in a flag and check it in the deleting routine of the unique_ptr .
  2. You could use polymorphism to provide two different classes that inherits from one interface class. The one class implements a deleter that does nothing and the other one implements one that actually call BN_free() .

Edit #2:

Now your code is more complete. You could write an addional constructor that takes a pointer to a const BIGNUM that uses an own dummy free function. You have to avoid the const_cast if you use this constructor.

BigNumber(const BIGNUM *src) : bn(src, ::BN_dummy_free) {}

The dummy free should look like this:

void BN_dummy_free(BIGNUM *a) {}

That should work with your code and will not end in a segmentation fault. So you could take allocated and non allocated BIGNUMs.

Also you should take care at your copy constructor, because it will always use BN_free() . You should copy the used deleter function, which could may be the BN_dummy_free() function.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM