0

I'm using memcpy to copy a specific number of chars from a char array to a char *. But when I read the char * have always trash in the end.

I'm using libssh2 lib to send commands to my raspberry pi and receive the output.

libssh2_channel_read will return the number of chars of the output int x and the output text will be on the char buffer[32].

Code I'm using:

char buffer[32];
int x = libssh2_channel_read(channel, buffer, sizeof(buffer));
char * output = (char *)malloc(sizeof(char)*x);
memcpy(output, buffer, x-2); // x - 2 because of "\r\n"
libssh2_channel_free(channel);
channel = NULL;
cout << output << endl;

Example of output:

0══²²²²

I only want the 0

16
  • 11
    So you are not copying the string terminator \0? Commented Jul 5, 2017 at 12:55
  • That is not the problem but don't cast the return of malloc as there is no need and may hide problems, see here on SO why. Commented Jul 5, 2017 at 12:57
  • have you checked the actual value of x? Commented Jul 5, 2017 at 12:57
  • 1
    @AndreKampling the answer you link says that one does not need to cast, but nothing about the cast being a real problem Commented Jul 5, 2017 at 12:58
  • 1
    @AndreKampling - stackoverflow.com/questions/3477741/… Commented Jul 5, 2017 at 13:07

3 Answers 3

9

Welcome to C++.

You are copying the values you care about but not the terminating '\0' character. Assuming x is valid (that is: x > 3 and x <= sizeof(buffer)) you can say:

output[x - 2] = '\0';

after the call to memcpy() and you should get what you expect.

However: when you're dealing with communications and buffers like this you need to be careful and check everything.

Sign up to request clarification or add additional context in comments.

4 Comments

Shouldn't that be output[x-2] ?
Correct!! if I do output[x - 2] = '\0' will work! Why x - 2? Because of the \r\n in the end of all commands.
@4386427 Yes, indeed!
@Samega7Cattac - because a C-style string requires a termination char with the value zero. So if you have abcdef\r\n and only copies abcdef into the new buffer using memcpy, you don't have the termination. So you must add '\0' after the memcpy to make it a valid C-style string.
0

I think you shouldn't be using raw arrays and memcpy and the like here.

You are probably better off with the containers from the C++ standard library:

Example:

std::vector<char> buffer(32);
int x = libssh2_channel_read(channel, &buffer[0], buffer.size());
// probably x will be smaller or equal the current size of the buffer
buffer.resize(x);
// if it's a string, why not have it as a std::string
std::string data(buffer.begin(), buffer.end());
std::cout << data << '\n';

2 Comments

This does not remove the \r\n at the end of the data
@NathanOliver Resizing a std::string or a std::vector is trivial. Stripping the string of trailing whitespace is left as an exercise for the reader.
0

Use std::string:

char buffer[32];
int x = libssh2_channel_read(channel, buffer, sizeof(buffer));
std::string output{ buffer, buffer + x - 2 };
libssh2_channel_free(channel);
channel = NULL;
cout << output << endl;

4 Comments

Can you explain why std::string output{ buffer, buffer + x - 2 };?
buffer + x one after the end of data, - 2 because of "\r\n"
@Samega7Cattac You give it the (address of) the first byte you want and of the first byte you don't want (one past the end less two for the CRLF).
@manni66 Ok, now I understand. But I need it to be char * because of other functions and converting string to char * sometimes can go bad

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.