The following code crashes while executing _strset_s I have given 80 as length in _strset_s. What could be the problem?. I enabled run time stack frame checkb option /RTCs
char strToken[80];
_strset_s(strToken, 80, '\0' );
You can let the compiler do the filling by using
char strToken[80] = {0};
This will zero all the bytes of the string.
The input to _strset_s has to be null terminated according to MSDN. Since your string is not initialized to anything, it violates this invariant.
If str is a null pointer, or the size argument is less than or equal to 0, or the block passed in is not null-terminated, then the invalid parameter handler is invoked,
The default "invalid parameter handler" is to crash, again from MSDN:
The default invalid parameter invokes Watson crash reporting, which causes the application to crash and asks the user if they want to load the crash dump to Microsoft for analysis.
So I'd try Null terminating strToken first (or better yet do what Bo Persson suggests in his answer)
char strToken[80];
strToken[79] = '\0';
_strset_s(strToken, 80, '\0' );
Related
Suppose you have a char buffer that you want to copy an std::string into. Are there consequences of copying extra data into the buffer, outside of the strings scope, even though the buffer has adequate size?
Example
std::string my_string = "hello";
char my_buffer[128];
memset(my_buffer, 0, 128);
strncpy(my_buffer, my_string.c_str(), 128);
So "hello" gets copied into my_buffer, but so will 123 other bytes of data that comes after my_string. Are there any consequences of this? Is it harmful for the buffer to hold this other data?
but so will 123 other bytes of data that comes after my_string
This assumption is incorrect: strncpy pays attention to null termination of the source string, never reading past null terminator. The remaining data will be set to '\0' characters:
destination is padded with zeros until a total of num characters have been written to it. [reference]
This is in contrast to memcpy, which requires both the source and the destination to be of sufficient size in order to avoid undefined behavior.
OK, let's assume what you wanted is:
strncpy(my_buffer, my_string.c_str(), 128);
Thsi is always a 0-terminated string by definition, so considering:
Copies at most count characters of the character array pointed to by src (including the terminating null character, but not any of the characters that follow the null character) to character array pointed to by dest.
You won't get anything copied after "hello" from the original string, the rest will be 0s:
If, after copying the terminating null character from src, count is not reached, additional null characters are written to dest until the total of count characters have been written.
According to strncpy() description here 1, the copy is done up to the length you provided, for null terminated string, so that when end of the string come before, like in this case, copy is done up to it and no more copy is done, so rest of the "123 bytes" are not copied, and the copy loop terminates
The other answers to this question have addressed what happens with strncpy() (i.e. it will copy your string correctly because it stops at the 0-terminator byte), so perhaps what gets more to the intent of the question would be, what if you had this instead?
memcpy(my_buffer, my_string.c_str(), 128);
In this case, the function (memcpy()) doesn't know about 0-terminated-string semantics, and will always just blindly copy 128 bytes (starting at the address returned by my_string.c_str()) to the address my_buffer. The first 6 (or so) of those bytes will be from my_string's internal buffer, and the remaining bytes will be from whatever happens to be in memory after that.
So the question is, what happens then? Well, this memcpy() call reads from "mystery memory" whose purpose you're not aware of, so you're invoking undefined behavior by doing that, and therefore in principle anything could happen. In practice, the likely result is that your buffer will contain a copy of whatever bytes were read (although you probably won't notice them, since you'll be using string functions that don't look past the 0/terminator byte in your array anyway).
There is a small chance, though, that the "extra" memory bytes that memcpy() read could be part of a memory-page that is marked as off-limits, in which case trying to read from that page would likely cause a segmentation fault.
And finally, there's the real bugaboo of undefined behavior, which is that your C++ compiler's optimizer is allowed to do all kinds of crazy modifications to your code's logic, in the name of making your program more efficient -- and (assuming the optimizer isn't buggy) all of those optimizations will still result in the program running as intended -- as long as the program follows the rules and doesn't invoke undefined behavior. Which is to say, if your program invokes undefined behavior in any way, the optimizations may be applied in ways that are very difficult to predict or understand, resulting in bizarre/unexpected behavior in your program. So the general rule is, avoid undefined behavior like the plague, because even if you think it "should be harmless", there's a very real possibility that it will end up doing things you wouldn't expect it to do, and then you're in for a long, painful debugging session as you try to figure out what's going on.
Assuming you mean definitely copying that data, as your current code would end at a null terminator.
Essentially, no. Whatever data is in there will be used only as string data so unless you then tried to do something weird with that spare data (try to put a function pointer to it and execute it etc.) then it's basically safe.
The issue is with initially copying random data past the end of your original string, that could overflow into protected data that you don't have access to and throw a segfault(Inaccessible memory exception)
Function strncpy will copy everything up to NUL character or specified size. That's it.
In addition to other answers please remember that strncpy does not NUL terminate the dst buffer when the src string length (excluding NUL) is equal to buffer's size given. You should always do something like my_buffer[127]=0 to prevent buffer overruns when handling the string later on. In libbsd there is strlcpy defined that always NUL terminate the buffer.
Check out this snippet:
#include <string.h>
int main(int argc, char ** argv)
{
char buf[8];
char *str = "deadbeef";
strlcpy(buf, str, sizeof(buf));
printf("%s\n", buf);
strncpy(buf, str, sizeof(buf));
printf("%s\n", buf);
return 0;
}
To see the problem compile it with flag -fsanitize=address. The second buffer is not NUL terminated!
I am working in visual studio 2010 and I received a project where the original programmer did this about half the time inside functions and methods
TCHAR some_local_variable[size] = {0};
and the other half of the time, he did not initialize the array:
TCHAR some_local_variable[size];
I am well aware of what the first assignment does, but I was wondering if the MSVC compiler guarantees a null character at index 0 in the second case.
I did test this out and the first character was set to 0 followed by garbage as expected, but I am not sure if this is guaranteed or not?
Secondly, even if a null character is guaranteed (or if it isn't, simply setting the first character to 0), is there any good reason to initialize the entire array with 0s, especially when I always do the following after any string manipulation:
some_local_variable[size-1] = 0;
My only thought is there could be a problem if the function manipulating the string did not null terminate AND the number of characters copied were less than size-1. For example, if it copied size-5 characters and did not null terminate, my termination at size-1 would potentially expose garbage in size-4 to size-2. However, I don't think is a problem with the majority of standard library or Win32 functions.
No, it doesn't. Uninitialized memory locations have random contents. (Debug builds may do some initialization to help detect memory corruption but that doesn't happen in release builds.)
You should not rely on any memory contents unless you explicitly initialized that memory region to some known value.
This question has details about the memory initialization for debug builds. (I'm not sure if the listings are complete.)
I have a server and a client. I am using winsock2. The client sends 4 bytes:
char *ack = new char[4];
sprintf( ack, "%d", counter );
sendto( clientSocket, ack, 4, 0, ( struct sockaddr* )&remote, sizeof( remote ) );
and the server receives these 4 bytes:
char* acks = new char[4];
if( ( bytes = recvfrom( serverSocket, acks, 4, 0, ( struct sockaddr* )&remote, &remote_size ) ) == SOCKET_ERROR ) {
cout << "socket error = " << WSAGetLastError() << endl;
break;
}
if( bytes > 0 ) {
sscanf( acks, "%d", &i );
}
I am getting this error and I can't figure out how to fix it:
>Critical error detected c0000374
>
>server.exe has triggered a breakpoint.
I know there is a problem with the pointer and the memory allocation. But my c++ skills are basic.
String formatting overflow
The most pressing issue is that you are using sprintf and sscanf. Avoid using sprintf and sscanf - they make it far too easy to accidentally create the type of bug you're seeing here, which is buffer overflow (on both your client and your server).
Consider what happens on your client when your 'counter' value is 1729. Your code will run
sprintf(ack, "%d", 1729);
The C-style-string representation of 1729 is five bytes long - one byte each for the char values '1', '7', '2', '9', and '\0'. But your ack buffer is only 4 bytes long! Now you've written that last zero byte into some chunk of memory you never allocated. In C/C++, this is undefined behavior, which means your program might crash, or it might not, and if it doesn't crash, it might end up subtly wrong later, or it might work perfectly well, or it might work most of the time except it breaks on Tuesdays.
It's not a good place to be.
You might be wondering, "if this is so awful, why didn't the sprintf just return an error or something I called it with a buffer that was too small?" The answer1 is that sprintf can't make that check because it doesn't give you any way to tell it how big ack actually is. When your code here is calling sprintf, you know that ack is 4 bytes long (since you just created it), but all sprintf sees is a pointer to some memory, somewhere - you haven't told it a length, so it just has to blindly hope the chunk of memory you give it is big enough.
Blindly hoping is a pretty bad way to write software.
There's a few alternatives you could consider here.
If you are actually just trying to send an int across the wire, there's not really any need to stringify the int at all - just send it in its native format by passing reinterpret_cast<char*>(&counter) as your buffer to sendto2 with sizeof(counter) as the corresponding buffer length. Use a similar construction in recvfrom on the other end. Note that this will break if your sender and your receiver have different underlying representations of ints (for example, if they use different endiannesses), but since you're talking about Winsock here I'm assuming you're assuming both ends are reasonably recent versions of Windows where that won't be a problem.
If you really do need to stringify the content first, use size-cognizant string conversion functions, like boost::format (which is implicitly size-cognizant because it deals in std::string instead of raw char* buffers) or _snprintf_s/_snscanf_s (which explicitly take in buffer length parameters, but are Microsoft-specific).
Recvfrom access violation
The overflow in sscanf/sprintf doesn't necessarily explain this, however:
I just want to add that the error occurs in the sscanf line. If I comment that line the error occurrs in the recvfrom line.
One possible explanation for this could be not providing adequate space for the remote address, though so long as your remote_size is a correct reflection of your remote, I'd expect this to cause recvfrom to return an error3, not crash. Another possibility is passing bad memory/handles (for example, if you've set up the new operator to not throw on failure, or if your socket initialization failed and you didn't bail out). It's impossible to say exactly without seeing the code initializing all the variables in play, and ideally the actual error you get in that scenario.
1 Even though sprintf can't catch this, static analysis tools (like those included in Visual Studio 2012/2013) are very capable of catching this particular bug. If you run the posted code through the default Visual Studio 2012 Code Analyzer, it will complain with:
error C4996: 'sprintf': This function or variable may be unsafe
2 Some people prefer static_cast<char*>(static_cast<void*>(&counter)) to reinterpret_cast<char*>(&counter). Both work, it's essentially a coding convention choice.
3 For example, if you were initializing remote as a SOCKADDR_IN instead of a SOCKADDR_STORAGE, you might encounter such an error if you happened to receive from an IPv6 address. This answer goes through some of the relevant gory details.
I am a c++ newbie and just try to write some code to have experiment myself.
Recently I have encountered a problem that I cannot debug.
char acExpReason[128];
char acReason[] = "An error message is information displayed when an unexpected condition occurs, usually on a computer or other device. On modern operating systems.";
memcpy(acExpReason, acReason, sizeof(acExpReason));
std::string strExpReason(acExpReason);
I use VS2005 to add breakpoints to every line to debug.
when it reaches the breakpoint on the second line, the variable name and value info in the Autos is:
acReason 0x00f6f78c "ÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌ" char [147]
acExpReason 0x00f6f828 "ÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌ̺" char [128]
when it reaches the breakpoint on the third line, the variable name and value info in the Autos is:
acExpReason 0x00f6f828 "ÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌ̺" char [128]
acReason 0x00f6f78c "An error message is information displayed when an unexpected condition occurs, usually on a computer or other device. On modern operating systems." char [147]
when it reaches the breakpoint on the fourth line, the variable name and value info in the Autos is:
acExpReason 0x00f6f828 "An error message is information displayed when an unexpected condition occurs, usually on a computer or other device. On modern ÌÌÌÌÌÌÌ̺" char [128]
acReason 0x00f6f78c "An error message is information displayed when an unexpected condition occurs, usually on a computer or other device. On modern operating systems." char [147]
strExpReason Bad Ptr
after the last line is executed, the info in Autos is:
acExpReason 0x00f6f828 "An error message is information displayed when an unexpected condition occurs, usually on a computer or other device. On modern ÌÌÌÌÌÌÌ̺" char [128]
acReason 0x00f6f78c "An error message is information displayed when an unexpected condition occurs, usually on a computer or other device. On modern operating systems." char [147]
strExpReason "An error message is information displayed when an unexpected condition occurs, usually on a computer or other device. On modern ÌÌÌÌÌÌÌ̺"
basically what my code wants to do is just to have a complete line of msg which is stored in acReason[], and also there is a copy of the complete msg in fixed length(here is 128).
but I don't know why acExpReason and strExpReason(the string version of the acExpReason) will end with some strange characters "ÌÌÌÌÌÌÌ̺" which I don't want(as I will use this string to compare with other string later).
I tried using memcpy, strcpy, and strncpy and they all ended up having that set of strange characters in the end of the string.
Can anyone help?
Many thanks in advance.
std::string strExpReason(acExpReason);
This constructor requires a C-style string. However acExpReason is not a C-style string since it does not have a terminating zero byte. (How would the constructor know how many bytes should be in the string?) You have to follow the rules.
In C all string functions like strcpy and also the constructor for c++'s std::string take char* as a parameter but the char* must be terminated with a byte containing `\0`.
acExpReason does not have a zero ending it so all the string functions look for the next 0 byte in memory. acReason does have a trailing `\0`. Normal strcpy would work as it also copies the 0 however as #VladLazarenko says the buffer size is too small which will cause all memory to be overwritten.
To make memcpy work you need to copy one less byte than the buffer and make the last byte of the buffer 0.
e.g.
memcpy(acExpReason, acReason, sizeof(acExpReason)-1);
acReason[sizeof(acExpReason)-1] = 0;
You can also use string constructor which accepts iterator range -
std::string strExpReason(acExpReason, acExpReason+sizeof(acExpReason));
//SECTION I:
void main()
{
char str[5] = "12345"; //---a)
char str[5] = "1234"; //---b)
cout<<"String is: "<<str<<endl;
}
Output: a) Error: Array bounds Overflow.
b) 1234
//SECTION II:
void main()
{
char str[5];
cout<<"Enter String: ";
cin>>str;
cout<<"String is: "<<str<<endl;
}
I tried with many different input strings, and to my surprise, I got strange result:
Case I: Input String: 1234, Output: 1234 (No issue, as this is expected behavior)
Case II: Input String: 12345, Output: 12345 (NO error reported by compiler But I was expecting an Error: Array bounds Overflow.)
Case III: Input String: 123456, Output: 123456 (NO error reported by compiler But I was expecting an Error: Array bounds Overflow.)
.................................................
.................................................
Case VI: Input String: 123456789, Output: 123456789(Error: unhandeled exception. Access Violation.)
My doubt is, When I assigned more characters than its capacity in SECTION I, compiler reported ERROR: Array bounds Overflow.
But, when I am trying the same thing in SECTION II, I am not geting any errors. WHY it is so ?? Please note: I executed this on Visual Studio
char str[5] = "12345";
This is a compiletime error. You assign a string of length 6 (mind the appended null-termination) to an array of size 5.
char str[5];
cin>>str;
This may yield a runtime error. Depending on how long the string is you enter, the buffer you provide (size 5) may be too small (again mind the null-termination).
The compiler of course can't check your user input during runtime. If you're lucky, you're notified for an access violation like this by Segmentation Faults. Truly, anything can happen.
Throwing exceptions on access violations is not mandatory. To address this, you can implement array boundary checking yourself, or alternatively (probably better) there are container classes that adapt their size as necessary (std::string):
std::string str;
cin >> str;
What you are seeing is an undefined behavior. You are writing array out of bounds, anything might happen in that case ( (including seeing the output you expect).
I tried with many different input strings, and to my surprise, I got
strange result:
This phenomena is called Undefined behavior (UB).
As soon as you enter more characters than a char array can hold, you invite UB.
Sometime, it may work, it may not work sometime, it may crash. In short, there is no definite pattern.
[side note: If a compiler allows void main() to get compiled then it's not standard compliant.]
It's because in the second case, the compiler can't know. Only at runtime, there is a bug. C / C++ offer no runtime bounds checking by default, so the error is not recognized but "breaks" your program. However, this breaking doesn't have to show up immediately but while str points to a place in memory with only a fixed number of bytes reserved, you just write more bytes anyways.
Your program's behavior will be undefined. Usually, and also in your particular case, it may continue working and you'll have overwritten some other component's memeory. Once you write so much to access forbidden memory (or free the same memory twice), your program crashes.
char str[5] = "12345" - in this case you didn't leave room to the null terminator. So when the application tries to print str, it goes on and on as long as a null is not encountered, eventually stepping on foridden memory and crashing.
In the `cin case, the cin operation stuffed 0 at the end of the string, so this stops the program from going too far in memory.
Hoever, from my experience, when breaking the rules with memory overrun, things go crazy, and looking for a reason why in one case it works while in other it doesn't, doesn't lead anywhere. More often than not, the same application (with a memory overrun) can work on one PC and crash on another, due to different memory states on them.
because compiler does static check. In your section II, size is unknown in advance. It depends on your input length.
May i suggest you to use STL string ?