【问题标题】:Pass raw pointer return by unique_ptr()::get() to a function taking double pointer as function parameter将 unique_ptr()::get() 返回的原始指针传递给以双指针作为函数参数的函数
【发布时间】:2021-09-13 15:48:21
【问题描述】:

代码编辑:https://gcc.godbolt.org/z/x3hnj46WY

场景-1 试图通过引用(或指针)传递原始指针 无法使用 & 将 get() 的值传递给 setBuffer() // 编译错误:需要左值作为一元 '&' 操作数

场景-2 通过获取原始字符指针分配值返回 使用 &

将 char 指针传递给 setBuffer()

注意:setBuffer() 存在于 C 库中 我正在使用这个 API https://www.libssh2.org/libssh2_session_last_error.html 来获取 errmsg 和 我想使用 char 数组的智能指针,而不是使用 char 数组缓冲区。

#include <string.h>
#include <iostream>
#include <memory>

int setBuffer(char ** ptr) {
    // ASSUMPTION: *ptr has sufficient memory to store copied data
    strcpy(*ptr, "sample string"); 
    return 0;
}
 
int main()
{
    std::unique_ptr<char []> lup = std::make_unique<char []>(1024);
    memset(lup.get(), 0 , 1024);
    
    strcpy(lup.get(), "sample string - 1");
    std::cout << lup << '\n';                   // c++20
   
    // SCENARIO - 1 | Compilation error
    setBuffer(&lup.get());  // CE: lvalue required as unary '&' operand
    
    // SCENARIO - 2 | Works fine
    char * lp = lup.get();
    setBuffer(&lp);
    
    std::cout << lup << '\n';                   // c++20
    
    return 0;
}

【问题讨论】:

  • 我很好奇你为什么选择std::unique_ptr&lt;char []&gt;而不是std::string
  • libssh2_session_last_error 的上下文中,该函数将自行设置指针。里面会有一个像*errmsg = some_internal_string_buffer; 这样的赋值,这意味着你对智能指针的使用无论如何都不会起作用(实际上会导致问题,因为lup 对象不会收到关于指针更改的通知)。如果要将返回的字符串作为 C++ 对象,则需要使用普通的原始非拥有指针开头,然后使用它来初始化 std::string(例如)。
  • 在实际程序中,我传递了一个 char [] 缓冲区,但出于学习目的,我想检查在从 C++ 调用此类 C 函数(如 setBuffer())时如何使用智能指针

标签: c++ unique-ptr raw-pointer c-libraries


【解决方案1】:

根据文档:

errmsg - 如果不为 NULL,则通过引用填充最新错误消息的人类可读形式。

我的阅读是它不会将任何错误消息复制到给定缓冲区,只会将指针设置为缓冲区(包含错误消息),存储在会话对象中。

因此用法如下所示:

char* errmsg = nullptr;
int errmsg_len = 0;
int ec = libssh2_session_last_error(session, &errmsg, &errmsg_len, /*want_buf=*/ 0);

printf("%s\n", errmsg);

另一方面,如果want_buf设置为非零值,将分配一个新的缓冲区,调用者负责稍后调用free

【讨论】:

  • 如果在任何地方都没有使用空字符串,你甚至可以初始化char* errmsg = nullptr;。文档所说的 not NULL 部分是指char** 参数,因此如果char* 级别指向NULL,它仍然有效。
  • 感谢您的回复在实际程序中,我传递了一个 char [] 缓冲区但出于学习目的,我想检查在从 C++ 调用此类 C 函数(如 setBuffer())时如何使用智能指针跨度>
猜你喜欢
  • 2019-08-17
  • 1970-01-01
  • 1970-01-01
  • 2018-08-25
  • 2019-08-22
  • 2016-11-07
  • 1970-01-01
  • 2021-03-10
相关资源
最近更新 更多