std::unique_ptr
может принимать пользовательское средство удаления, которое позволяет ему управлять памятью, выделенной OpenSSL. То, какая именно функция должна вызываться для очистки, зависит от того, какая функция выделяет ее, но для примера i2d_RSAPublicKey
, который вы использовали в своем примере, она должна обернуть OPENSSL_free
:
struct OpenSSLFree
{
void operator()(void* ptr)
{
OPENSSL_free(ptr);
}
};
template <typename T>
using OpenSSLPointer = std::unique_ptr<T, OpenSSLFree>;
OpenSSLPointer<unsigned char> EncodeRSAPublicKey(RSA* key)
{
unsigned char* out = nullptr;
int status = i2d_RSAPublicKey(key, &out);
if (status < 0) {
// handle error
}
return OpenSSLPointer<unsigned char>{out};
}
Буфер, содержащий закодированный ключ, будет очищен исключительным образом.
Вы также можете использовать std::vector<unsigned char>
в этом случае. Вам придется вызывать i2d_RSAPublicKey
дважды: один раз, чтобы получить требуемый размер буфера, и снова, чтобы фактически кодировать данные:
std::vector<unsigned char> EncodeRSAPublicKey(RSA* key)
{
int len = i2d_RSAPublicKey(key, nullptr);
if (len < 0) {
// handle error
}
std::vector<unsigned char> outVec(len);
unsigned char* outPtr = outVec.data();
len = i2d_RSAPublicKey(key, &outPtr);
if (len < 0) {
// handle error
}
return outVec;
}
Это, вероятно, более чистый интерфейс, но он не будет работать везде. std::unique_ptr
с пользовательским подходом к удалению широко применяется, но, опять же, функция, вызываемая средством удаления, будет зависеть от того, как распределена память.