-2

Code edit: https://gcc.godbolt.org/z/x3hnj46WY

Scenario -1 Trying to pass raw pointer by reference (or pointer) can't pass value of get() using & to setBuffer() // Compilation error : lvalue required as unary '&' operand

Scenario -2 Assign value return by get to a raw char pointer Pass char pointer to setBuffer() using &

NOTE: setBuffer() is present in a C library I am using this API https://www.libssh2.org/libssh2_session_last_error.html to get errmsg and instead of using a char array buffer I want to use smart pointer of char array.

#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;
}
  • I'm curious about why you picked `std::unique_ptr` instead of `std::string`? – Some programmer dude Sep 13 '21 at 06:46
  • And in the context of `libssh2_session_last_error`, then that function will set the pointer itself. Inside there will be an assignment like `*errmsg = some_internal_string_buffer;` Meaning your use of smart pointers won't work anyway (and will actually lead to problems since the `lup` object will not be notified about the pointer change). If you want the returned string as a C++ object, then you need to use a plain raw non-owning pointer to begin with, and then use it to initialize a `std::string` (for example). – Some programmer dude Sep 13 '21 at 06:48
  • In actual program I passed a char [] buffer But for learning purpose I wanted to check how to use smart pointer when calling such C function (as setBuffer()) from C++ – Ratnesh Tiwari Sep 13 '21 at 11:42

1 Answers1

1

According to the docs:

errmsg - If not NULL, is populated by reference with the human readable form of the most recent error message.

My reading is that it will not copy any error message to the given buffer, only set the pointer to a buffer (that contains the error message), stored in the session object.

Therefore usage would look like this:

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

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

On the other hand, if want_buf is set to a non-zero value, a new buffer will be allocated, and the caller is responsible to call free on it later.

erenon
  • 18,838
  • 2
  • 61
  • 93
  • You can even initialize `char* errmsg = nullptr;` if there is no use of the empty string anywhere. The *not NULL* part that the docs are talking about refers to the `char**` argument, so it still works if the `char*` level points to `NULL`. – ComicSansMS Sep 13 '21 at 07:07
  • Thanks for your response In actual program I passed a char [] buffer But for learning purpose I wanted to check how to use smart pointer when calling such C function (as setBuffer()) from C++ – Ratnesh Tiwari Sep 13 '21 at 11:47