0

I am trying to flush out a char buffer by using strcpy(buffer, ""). strcpy() seems to be putting random numbers in the string. In gdb, I see the buffers (received_message):

Before strcpy() call:

(gdb) print received_message
$6 = "9210070627\000\000\000\000\000\000\000\000\000"

After strcpy() call:

(gdb) print received_message
$8 = "\000\062\061\060\060\067\060\066\062\067\000\000\000\000\000\000\000\000\000"

Where \060 ... \067 = 48 ... 65.

My strcpy() call in the code is simply strcpy(received_message, "");, so I am not sure what is going on.

I have solved the actual issue by just putting in a null terminator rather than trying to make the string empty since I know the length of the string, but I am still very curious about what is going on here.

EDIT: It seems that some people want some more background on why I am doing this. I was doing this as I am using zmq, which sends and received strings without the null terminator. I was running into a problem in a test where I was doing the following:

Send 1234
Receive 1234
Send 123
Receive 1234
Send 12345
Receive 12345
Send 1234
Receive 12345

What seemed to be happening is that I was reusing my buffer for receiving messages (received_message), which was retaining values if the previous string was longer than the one that was being received.

To fix this, I wanted to "flush" the buffer, meaning I wanted to set it all to null characters. From reading some other answers, it seemed that strcpy(received_message, "") would do the trick, as would recived_message[0] = 0. However, neither of these would work as they only set the first character to null. I knew of the memset() method of "flushing" the buffer, but read that it was a bit slower than something such as strcpy(received_message, ""), so did not use it. The solution I figured out (and show below) avoids setting the whole array with memset(), so I am a bit happier with it, although it likely makes no difference at all.

What confused me is the fact that this strcpy() call replaced what was originally a number in a string by the individual numbers prefixed with \06, which I has mistaken for ASCII characters such as \060 rather than 0 prefixed by \06.

I have fixed the issue with receiving the message since zmq_recv() returns the string length without the null terminator, so to put a null character at the end of the received message, we only need to do

int received_length = zmq_recv(request_socket, received_message, 20, 0);
received_message[received_length] = 0;

In this case, received message is a 20-element array of char and I'm worried about receiving messages longer than that in this case.

After solving the problem, I was still curious about what was going on with my strcpy() call, although I was not correctly understanding what was happening. I am still curious why the numbers were being prefixed with \06 though.

Daniel Underwood
  • 2,191
  • 2
  • 22
  • 48

2 Answers2

4

You should not use

 strcpy(buffer, "")

to flush a buffer. It only copies "" to the destination and leaves the rest of the area of buffer untouched.

That is why, you can see the previous values are retained.

To elaborate, as we can see, the buffer was having a value "9210070627", after the strcpy(buffer, ""), the "9" is replaced by the \0, but the remaining values persisit in the buffer.

Check ASCII table for the values.

Maybe, what you want is

memset(buffer, 0, sizeof(buffer)); //buffer is char[]

or

memset(buffer, 0, strlen(buffer)); //buffer is char*
Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
3

It is unclear what you intended to do, but the code does exactly what you told it to do.

A C "string" is a series of char elements that ends with a null value. Whatever comes after that null value is not part of the string.

Your string before the call:

"9210070627" (followed by a null value, and a series of null values that might be part of the buffer or an artifact of the debugger, we don't know).

Your call:

strcpy(buffer, "") (copy empty string into buffer, and terminate with null value)

Your string after the call:

"" -- an empty string, followed by the terminating null value (plus the "210070627" and null values remaining from the previous content as artifacts which aren't part of the string as mentioned above).

So, your buffer now contains an empty string, as you instructed. It also contains remains of the original data, but buffer does point to an empty string. strlen( buffer ) == 0.

If you are intending to erase the contents of the buffer, i.e. zero-out the whole buffer, you should try memset().

DevSolar
  • 67,862
  • 21
  • 134
  • 209
  • This makes a lot more sense now. I was thinking that the characters such as `\060` were ASCII integers, but your answer made me realize that it was just the original value prefixed with `\06`. I'm guessing that this `\06` is an indicator of an integer or something like that? Also, what is causing the `strcpy()` call to change the array to be formatted like this instead of just a string of the numbers? – Daniel Underwood May 26 '15 at 13:55
  • @danielu13 no, it's not `\06`, its `\060`, in octal, which is char `'0'`. Simmilar for other values, check the link in my asnwer. :-) – Sourav Ghosh May 26 '15 at 13:56
  • @danielu: `\060` is an integer literal in octal notation, equal to decimal `48`, which happens to be the ASCII value of the letter `'0'`. (`\061` is `49` is `'1'` and so on.) The array isn't "formatted" at all. But the debugger doesn't know that the stuff after the terminating `\0` should be interpreted as string as well (*because it isn't part of the string*), so instead of printing ASCII (and risking it to be lots of funny but meaningless characters), it prints octal literals to tell you of the raw data in memory. The in-memory values are not changed at all by the `strcpy()`. – DevSolar May 26 '15 at 13:58
  • Ahh. I was thinking it meant the decimal 48, but did not think of it as corresponding to the character `'0'`. @DevSolar, I now understand why it printed in octal rather than ASCII, but why did it print in ASCII when I printed the variable right before the `strcpy()` call? – Daniel Underwood May 26 '15 at 14:09
  • @danielu13: Because the debugger was smart enough to figure it out. Had you printed the buffer via `puts()`, the results would have been exactly as expected. You were confused by the debugger, not anything your code did or didn't. – DevSolar May 26 '15 at 14:12
  • So possibly the debugger didn't know how to interpret the buffer after the `strcpy()` call since it began with a null character and thus wasn't exactly a string? – Daniel Underwood May 26 '15 at 14:16
  • @danielu13: That's what I said, yes. It "knows" `buffer` is of type `char []`, and thus prints the contents as string. But by definition, the first `\0` terminates the string, and the rest is printed as raw data. – DevSolar May 26 '15 at 14:19