Reputation: 327
I'm trying to implement some openssl functionality in a C++ program. The openssl library requires a lot of memory allocation / deallocation. My approach is to pack the required structs from openssl into a class and allocate the memory with the constructor and deallocate it via the destructor.
Now I wanted to move to a different approach where each member is represented as a unique pointer with a deleter. This would mean that I would not have to rely on the destructor of the object to release the memory.
Let's say my class looks like this:
class OpensslSignature {
public:
OpensslSignature() = default;
std::unique_ptr<X509, decltype(X509_free) *> cert{nullptr, X509_free};
std::unique_ptr<EVP_PKEY, decltype(EVP_PKEY_free) *> pkey{nullptr, EVP_PKEY_free};
void readCert(const std::string &name);
void readKey(const std::string &key);
}
The implementation is like this:
void OpensslSignature::readCert(const std::string &name) {
BIO *tmp = BIO_new_file(name.c_str(), "r");
cert = std::unique_ptr<X509, decltype(X509_free) *>(PEM_read_bio_X509(tmp, NULL, 0, NULL), X509_free);
BIO_free(tmp);
if (!cert) {
// error handling
}
}
void OpensslSignature::readKey(const std::string &key) {
// similiar to readCert
}
Is it correct to initialize unique_ptrs like this? Am I supposed to set them to nullptr in the header? Or would it be better to initialize them in a constructor?
Also when initializing the pointer in the readCert() function, do I really need to write the entire pointer definition again std::unique_ptr<type, deleter>()
?
Or is it better to initialize with std::make_unique()?
Upvotes: 1
Views: 962
Reputation: 179991
The general C++ principle here is RAII - Resource Acquisition Is Initialization. It's quite easy to search for that term online.
It also means that Initialization Is Resource Acquisition. Objects generally shouldn't be initialized to some unusable, empty state, where you then need to call another function to do the real work.
In this case, it looks like OpensslSignature
has two parts, both of which should be classes in their own right. X509_free
should be called from the destructor of some kind of Cert-type, while EVP_PKEY_free
should be called from the destructor of some kind of "KeyPair" type.
The OpensslSignature
constructor can then take those two types, and you won't need a readCert
function anymore.
You can use a unique_ptr
in both of the implementations, if you like. I'm not sure if that's exactly the easiest route, but that's a small matter. You'd make it private
anyway, and if you later change the implementation that won't matter to code outside that class.
Upvotes: 1