I am doing a simple communication between sockets and here is my C++ code
while(1)
{
string buffer = "23,45\n";
const char* foo = buffer.c_str();
cout << "size of buffer is " << sizeof(buffer)<<endl;
send (s, foo, sizeof(buffer), 0);
}
weird thing is the fist iteration, the size of the buffer is 5 as expected, but since the second iteration and so on, the size dramatically jumped to 32. any idea why? Thank you very much. By the way, the added size comes from leading while spaces.
The sizeof operator returns the size (in bytes) of the object. It doesn't return the length of a container type. You need to use std::string::length() or std::string::size() to determine the length of the string.
I think you misunderstood the 5 of the first iteration: it must be coming from somewhere else. sizeof(buffer) is figured out at compile time - it is the size of std::string, so you should see 32 on every iteration.
If you are looking for the length of the string, use buffer.size() instead.
sizeof(buffer) tells you the size of your std::string object, which has nothing to do with the number of characters you store in it (which by the way are 7 in your example, not 5).
Related
I am new to c++ and am still figuring out file streams. I am trying to put a character array into a file that I will be viewing with a hex editor.
I have done different strings, but whenever I put in a null byte, the file ends.
ofstream stream;
char charArray[256];
for (int i = 0; i <= 255; i++)charArray[i] = i;
stream.open("C:\\testfile.myimg");
if (!stream.is_open()) exit(1);
stream << charArray << endl;
return 0;
I want to output bytes with ascending values, but if I start with the null byte, then c++ thinks the character array ends before it starts
Instead of:
stream << charArray << endl;
use:
stream.write(charArray, sizeof(charArray));
stream.write("\n", 1); // this is the newline part of std::endl
stream.flush(); // this is the flush part of std::endl
The first one assumes that you are sending a null-terminated string (because you're passing a char* - see the end of the answer why). That's why when the code encounters the very first char with value 0, which is '\0' (the null-terminator), it stops.
On the other hand, the second approach uses an unformatted output write, which will not care about the values inside charArray - it will take it (as a pointer to its first element) and write sizeof(charArray) bytes starting from that pointer to the stream. This is safe since it's guaranteed that sizeof(char) == 1, thus sizeof(charArray) will yield 256.
What you need to consider is array decaying. It will work in this case (the sizeof thing), but it will not work if you simply pass a decayed pointer to the array's first element. Read more here: what's array decaying?
I'd like to start with the fact that I'm still learning C++ and some of the things still baffles me.
What I'm trying to accomplish is to build a byte stream to send over a socket. I'm trying to create a packet 1536 bytes in length for a handshake
std::stringstream s1Stream;
char randData[1528], zeroVal[4] = {0, 0, 0, 0};
memset(&randData, 1, sizeof(randData)); // Fill the buffer with data
s1Stream << timestampVal; // 4 bytes
s1Stream << zeroVal; // 4 bytes
s1Stream << randData; // 1528 bytes
When I convert s1Stream to string and check the size() of that string the program says that the size is 1541.
What am I doing wrong?
std::stringstream's operator<<(char const*), which is used here, treats its argument as zero-terminated C-style strings, and your randData array is not zero-terminated.
Since randData is not really a C-style string and looks like it could end up containing null bytes, the fix is to use
s1Stream.write(randData, sizeof(randData));
Note that this problem applies with zeroVal as well, except nothing of zeroVal will be written to s1Stream because it is zero-terminated at the first byte.
I'm having a string is not null terminated error, though I'm not entirely sure why. The usage of std::string in the second part of the code is one of my attempt to fix this problem, although it still doesn't work.
My initial codes was just using the buffer and copy everything into client_id[]. The error than occurred. If the error is correct, that means I've got either client_ id OR theBuffer does not have a null terminator. I'm pretty sure client_id is fine, since I can see it in debug mode. Strange thing is buffer also has a null terminator. No idea what is wrong.
char * next_token1 = NULL;
char * theWholeMessage = &(inStream[3]);
theTarget = strtok_s(theWholeMessage, " ",&next_token1);
sendTalkPackets(next_token1, sizeof(next_token1) + 1, id_clientUse, (unsigned int)std::stoi(theTarget));
Inside sendTalkPackets is. I'm getting a string is not null terminated at the last line.
void ServerGame::sendTalkPackets(char * buffer, unsigned int buffersize, unsigned int theSender, unsigned int theReceiver)
{
std::string theMessage(buffer);
theMessage += "0";
const unsigned int packet_size = sizeof(Packet);
char packet_data[packet_size];
Packet packet;
packet.packet_type = TALK;
char client_id[MAX_MESSAGE_SIZE];
char theBuffer[MAX_MESSAGE_SIZE];
strcpy_s(theBuffer, theMessage.c_str());
//Quick hot fix for error "string not null terminated"
const char * test = theMessage.c_str();
sprintf_s(client_id, "User %s whispered: ", Usernames.find(theSender)->second.c_str());
printf("This is it %s ", buffer);
strcat_s(client_id, buffersize , theBuffer);
Methinks that problem lies in this line:
sendTalkPackets(next_token1, sizeof(next_token1) + 1, id_clientUse, (unsigned int)std::stoi(theTarget));
sizeof(next_token1)+1 will always gives 5 (on 32 bit platform) because it return size of pointer not size of char array.
One thing which could be causing this (or other problems): As
buffersize, you pass sizeof(next_token1) + 1. next_token1 is
a pointer, which will have a constant size of (typically) 4 or 8. You
almost certainly want strlen(next_token1) + 1. (Or maybe without the
+ 1; conventions for passing sizes like this generally only include
the '\0' if it is an output buffer. There are a couple of other
places where you're using sizeof, which may have similar problems.
But it would probably be better to redo the whole logic to use
std::string everywhere, rather than all of these C routines. No
worries about buffer sizes and '\0' terminators. (For protocol
buffers, I've also found std::vector<char> or std::vector<unsigned char>
quite useful. This was before the memory in std::string was
guaranteed to be contiguous, but even today, it seems to correspond more
closely to the abstraction I'm dealing with.)
You can't just do
std::string theMessage(buffer);
theMessage += "0";
This fails on two fronts:
The std::string constructor doesn't know where buffer ends, if buffer is not 0-terminated. So theMessage will potentially be garbage and include random stuff until some zero byte was found in the memory beyond the buffer.
Appending string "0" to theMessage doesn't help. What you want is to put a zero byte somewhere, not value 0x30 (which is the ascii code for displaying a zero).
The right way to approach this, is to poke a literal zero byte buffersize slots beyond the start of the buffer. You can't do that in buffer itself, because buffer may not be large enough to accomodate that extra zero byte. A possibility is:
char *newbuffer = malloc(buffersize + 1);
strncpy(newbuffer, buffer, buffersize);
newbuffer[buffersize] = 0; // literal zero value
Or you can construct a std::string, whichever you prefer.
First question: I am confused between Buffers in TCP. I am trying to explain my proble, i read this documentation TCP Buffer, author said a lot about TCP Buffer, thats fine and a really good explanation for a beginner. What i need to know is this TCP Buffer is same buffer with the one we use in our basic client server program (Char *buffer[Some_Size]) or its some different buffer hold by TCP internally ?
My second question is that i am sending a string data with prefix length (This is data From me) from client over socket to server, when i print my data at console along with my string it prints some garbage value also like this "This is data From me zzzzzz 1/2 1/2....." ?. However i fixed it by right shifting char *recvbuf = new char[nlength>>3]; nlength to 3 bits but why i need to do it in this way ?
My third question is in relevance with first question if there is nothing like TCP Buffer and its only about the Char *buffer[some_size] then whats the difference my program will notice using such static memory allocation buffer and by using dynamic memory allocation buffer using char *recvbuf = new char[nlength];. In short which is best and why ?
Client Code
int bytesSent;
int bytesRecv = SOCKET_ERROR;
char sendbuf[200] = "This is data From me";
int nBytes = 200, nLeft, idx;
nLeft = nBytes;
idx = 0;
uint32_t varSize = strlen (sendbuf);
bytesSent = send(ConnectSocket,(char*)&varSize, 4, 0);
assert (bytesSent == sizeof (uint32_t));
std::cout<<"length information is in:"<<bytesSent<<"bytes"<<std::endl;
// code to make sure all data has been sent
while (nLeft > 0)
{
bytesSent = send(ConnectSocket, &sendbuf[idx], nLeft, 0);
if (bytesSent == SOCKET_ERROR)
{
std::cerr<<"send() error: " << WSAGetLastError() <<std::endl;
break;
}
nLeft -= bytesSent;
idx += bytesSent;
}
std::cout<<"Client: Bytes sent:"<< bytesSent;
Server code:
int bytesSent;
char sendbuf[200] = "This string is a test data from server";
int bytesRecv;
int idx = 0;
uint32_t nlength;
int length_received = recv(m_socket,(char*)&nlength, 4, 0);//Data length info
char *recvbuf = new char[nlength];//dynamic memory allocation based on data length info
//code to make sure all data has been received
while (nlength > 0)
{
bytesRecv = recv(m_socket, &recvbuf[idx], nlength, 0);
if (bytesRecv == SOCKET_ERROR)
{
std::cerr<<"recv() error: " << WSAGetLastError() <<std::endl;
break;
}
idx += bytesRecv;
nlength -= bytesRecv;
}
cout<<"Server: Received complete data is:"<< recvbuf<<std::endl;
cout<<"Server: Received bytes are"<<bytesRecv<<std::endl;
WSACleanup();
system("pause");
delete[] recvbuf;
return 0;
}
You send 200 bytes from the client, unconditionally, but in the server you only receive the actual length of the string, and that length does not include the string terminator.
So first of all you don't receive all data that was sent (which means you will fill up the system buffers), and then you don't terminate the string properly (which leads to "garbage" output when trying to print the string).
To fix this, in the client only send the actual length of the string (the value of varSize), and in the receiving server allocate one more character for the terminator, which you of course needs to add.
First question: I am confused between Buffers in TCP. I am trying to
explain my proble, i read this documentation TCP Buffer, author said a
lot about TCP Buffer, thats fine and a really good explanation for a
beginner. What i need to know is this TCP Buffer is same buffer with
the one we use in our basic client server program (Char
*buffer[Some_Size]) or its some different buffer hold by TCP internally ?
When you call send(), the TCP stack will copy some of the bytes out of your char array into an in-kernel buffer, and send() will return the number of bytes that it copied. The TCP stack will then handle the transmission of those in-kernel bytes to its destination across the network as quickly as it can. It's important to note that send()'s return value is not guaranteed to be the same as the number of bytes you specified in the length argument you passed to it; it could be less. It's also important to note that sends()'s return value does not imply that that many bytes have arrived at the receiving program; rather it only indicates the number of bytes that the kernel has accepted from you and will try to deliver.
Likewise, recv() merely copies some bytes from an in-kernel buffer to the array you specify, and then drops them from the in-kernel buffer. Again, the number of bytes copied may be less than the number you asked for, and generally will be different from the number of bytes passed by the sender on any particular call of send(). (E.g if the sender called send() and his send() returned 1000, that might result in you calling recv() twice and having recv() return 500 each time, or recv() might return 250 four times, or (1, 990, 9), or any other combination you can think of that eventually adds up to 1000)
My second question is that i am sending a string data with prefix
length (This is data From me) from client over socket to server, when
i print my data at console along with my string it prints some garbage
value also like this "This is data From me zzzzzz 1/2 1/2....." ?.
However i fixed it by right shifting char *recvbuf = new
char[nlength>>3]; nlength to 3 bits but why i need to it in this way ?
Like Joachim said, this happens because C strings depend on the presence of a NUL-terminator byte (i.e. a zero byte) to indicate their end. You are receiving strlen(sendbuf) bytes, and the value returned by strlen() does not include the NUL byte. When the receiver's string-printing routine tries to print the string, it keeps printing until if finds a NUL byte (by chance) somewhere later on in memory; in the meantime, you get to see all the random bytes that are in memory before that point. To fix the problem, either increase your sent-bytes counter to (strlen(sendbuf)+1), so that the NUL terminator byte gets received as well, or alternatively have your receiver manually place the NUL byte at the end of the string after it has received all of the bytes of the string. Either way is acceptable (the latter way might be slightly preferable as that way the receiver isn't depending on the sender to do the right thing).
Note that if your sender is going to always send 200 bytes rather than just the number of bytes in the string, then your receiver will need to always receive 200 bytes if it wants to receive more than one block; otherwise when it tries to receive the next block it will first get all the extra bytes (after the string) before it gets the next block's send-length field.
My third question is in relevance with first question if there is
nothing like TCP Buffer and its only about the Char *buffer[some_size]
then whats the difference my program will notice using such static
memory allocation buffer and by using dynamic memory allocation buffer
using char *recvbuf = new char[nlength];. In short which is best and
why ?
In terms of performance, it makes no difference at all. send() and receive() don't care a bit whether the pointers you pass to them point at the heap or the stack.
In terms of design, there are some tradeoffs: if you use new, there is a chance that you can leak memory if you don't always call delete[] when you're done with the buffer. (This can particularly happen when exceptions are thrown, or when error paths are taken). Placing the buffer on the stack, on the other hand, is guaranteed not to leak memory, but the amount of space available on the stack is finite so a really huge array could cause your program to run out of stack space and crash. In this case, a single 200-byte array on the stack is no problem, so that's what I would use.
Can anyone spot the reason why nothing gets printed onto console using below C++ code;
string array[] = { "a", "b", "c", "d" };
int length = sizeof(array);
try
{
for (int i = 0; i < length; i++)
{
if (array[i] != "") cout << array[i];
}
}
catch (exception &e)
{
e.what();
}
You use the wrong length:
int length = sizeof(array)/sizeof(array[0])
The actual reason you don't see anything on the console is because the output is buffered, and since you haven't wrote a newline it's not flushed. In the meantime your app crashes.
No end of line character.
Also as mentioned by Dave, sizeof is not the length of the array
This answer assumes that string == std::string.
let T be an arbitrary type, and n be an arbitrary positive integer - then:
sizeof(T[n]) == n * sizeof(T)
That is - sizeof(array) is not the length of the array, but the total amount of memory used by the array (in chars). Your std::string implementation could very well be using more than 1 char's worth of memory to store its structure. This leads to length holding a value much greater than 4.
This causes the program to read from past the end of array; an operation for which C++ imposes no requirements (it is Undefined Behaviour).
In terms of the C++ abstract machine, a program containing Undefined Behaviour can do absolutely anything, even before the point in the execution of the program at which the Undefined Behaviour was encountered. In your particular case your program exhibits this behaviour by not printing anything (even though you had made 4 well defined calls to operator<< before the erroneous array indexing).
You have tagged this eclipse-cdt, so I will assume that you are using GCC to compile your program, and are running it under a modern operating system with memory-protection. In this case the actual reason for the behaviour that you are seeing is probably that std::cout is buffering the first few strings that you stream into it and so not immediately printing them to the console. After that you get to the buffer overrun and your operating system interrupts the process with a EXC_BAD_ACCESS signal or similar. This causes the immediate termination of your program, which does not give std::cout a chance to flush its buffered values. All up, this means that nothing gets printed.
As mentioned in another answer, you should replace the line:
length = sizeof(array);
with:
length = sizeof(array)/sizeof(array[0]);
This will guarantee that length will hold the value 4, rather than the value 4 * sizeof(string), that could be many times the length of the array.