C ++:将指针的指针传递给函数

时间:2019-06-11 06:36:17

标签: c++ pointers openssl

我是C ++的新手,正在尝试将Openssl集成到我的项目中。例如此处的某些功能i2d_RSAPublicKey接收unsigned char**作为第二个参数,并在其中存储一些数据。我在这里曾问过类似的问题:

How to manage C++ principles with C compatible libraries and APIs

但是由于在这里使用std::stringstd::vector并不方便,所以我决定再问一个问题。

由于std::string::c_str()返回const行指针,而std::vector::data()仅返回行指针,因此它们与此功能不兼容。另外,我不认为操纵行指针将数据存储在std::stringstd::vector中是一个好主意。

所以我的问题是,我应该使用哪种数据类型以不违反RAII标准,并将指针的指针传递给将在其中存储一些数据的函数?

1 个答案:

答案 0 :(得分:2)

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广泛适用,但是删除器要调用的功能将再次取决于内存的分配方式。