I would like to know how does cin.get() function works?
For example, I have char array of 256 characters. If input contains less than 256 characters, what's 'empty' array elements containing then? Is every unused element is '\0' or what?
Thanks in advance,
Janis
For example, You have a simple code and you entered a string "ex: Hello world!" as follow:
char str[256]; // Uninitialized variable
std::cin.get(str, 256);
The result:
The same code but with initialized variable:
char str[256] = {}; // Initialized variable
std::cin.get(str, 256);
The result:
The part of the array that is not filled is untouched. If the array is fresh, typically you see zeros, as the operating system zeros out newly allocated pages. Consider this an artifact, expect anything.
get() is an overloaded function of the basic_istream class. Assuming you are calling it like:
cin.get(array, size)
Then it will fill up to size - 1 characters in the array. The rest are leaved unmodified, so you cannot know the value they have.
If input contains less than 256 characters, what's 'empty' array elements containing then? Is every unused element is '\0' or what?
It depends.
Global and static variables are default initialized. Local variables are uninitialized - unless you explicitly initialize them.
char buf1[256]; // global variable, all zeroes
int main() {
char buf2[256]; // uninitialized memory
}
Reading from buf1 has well defined behavior but reading from buf2 has not, so if you std::cin.get(buf2, <some_size>); and read from the memory beyond the \0 that std::cin.get() puts in your array, your program will have undefined behavior.
To amend that, you can default initialize your local variables too:
int main() {
char buf2[256]{}; // default initialized memory
}
Related
I am recreating the string class using char arrays. My problem is, when I allocate memory for a larger array, it generates an array that is completely the wrong size.
For example:
int allocated = 4;
char * reservedString = new char[allocated];
cout << strlen(reservedString);
Instead of creating a character array of size 4, reservedString points to a character array with 14 spots containing random characters.
This is what the debug shows me. Reserved string is now the wrong size with a bunch of random characters in it. When I try to use strcpy or strcpy_s it is writing memory out of bounds because the new array sizes are wrong.
How can I create a char array with an unknown length, which is provided by a variable, that is right size.
I can not use the std::string class or std::vector.
When you are creating an object with the new operator, your data remains not initialized. The code you provide is basically an array of bytes.
The documentation about strlen says:
computes the length of the string str up to, but not including the terminating null character.
There is no null terminator here.
You should do:
int allocated = 4;
char * reservedString = new char[allocated]();
This will initialize your array and set all the elements to \0
strlen expects a null-terminated string, which means a string that ends in a null character (\0). You're passing to it a pointer pointing to newly allocated memory, which contains uninitialized values and reading it causes undefined behavior. So when strlen searches for a null character in order to determine the length of the string, stuff is going to go wrong.
You cannot determine the size of an array given only a pointer to it unless you know it's going to be terminated by a null character or something similar. So either properly initialize the array with a null-terminated string or keep track of the length yourself.
I'm so confused, I'm sorry if this obvious, but:
int main()
{
char stringDest[20];
char stringSource[20];
strcpy_s(stringDest, stringSource);
return 0;
}
Throws the exception "Buffer is too small". Whereas:
char stringSource[20];
int main()
{
char stringDest[20];
strcpy_s(stringDest, stringSource);
return 0;
}
Works fine.
Furthermore, I thought the point of the safe strcpy_s(dest, size, source) was that you specify the number of bytes that are copied, however when I do this:
int main()
{
char stringDest[20];
char stringSource[20];
strcpy_s(stringDest, 1, stringSource);
return 0;
}
I get a "Buffer is too small exception".
I am so confused. Why does declaring the variable outside main() make a difference? And why is it wrong to specify 1 byte to copy?
Gives me an unhandled RangeChecks exception, whereas:
C's arrays are zero indexed, that means for char stringSource[20];, the elements are from 0 to 19, when you do stringSource[20] = '\0';, the access is out of array bounds, which results undefined behavior.
Throws the exception "Buffer is too small". Whereas:
That's because stringSource is of automatic storage and is not initialized to a valid string, use of it cause undefined behavior.
While the second case, when you put char stringSource[20]; out of the function, the array is static storage, it is by default initialized with zero value, it is effectively the same as char stringSource[20] = "";, that's why this case the strcpy succeeded.
You are invoking undefined behaviour here, because you are not initializing the source string.
In most cases, there will be garbage, and the first 0 byte is most likely after the length of 20, which is why the compiler/runtime complaines.
char stringSource[20] = {0};
or alternatively
char stringSource[20] = "";
Whatever suits best.
Depending on your environment, in the debug version, the compiler can intentionally fill the variables with values like 0xff so that the first 0-byte will always be beyond the limit.
If you put char stringDest[20] outside the function it will be a global variable, which are always iniatlized to 0 by the CRT startup.
In your last example, you should take a look at the description of strcpy_s.
This variant will cause an error if
destsz is less or equal strnlen_s(src, destsz); in other words, truncation would occur
strcpy_s(stringDest, 1, stringSource); means that 1 is smaller than your uninitialized stringlen, so it gives an error.
Note, that this parameter does not tell the function how many characters it should copy, but how big the destination is supposed to be. You don't tell it to copy only 1 character, you tell it, that it can copy at most 1 character ( which would be needed for the 0 byte anyway).
When I call gethostname using a char my length 25 but when I use a string my length is 64. Not really sure why. Both of them I am declaring the same size on HOST_NAME_MAX.
char hostname[HOST_NAME_MAX];
BOOL host = gethostname(hostname, sizeof hostname);
expectedComputerName = hostname;
int size2 = expectedComputerName.length();
std::string test(HOST_NAME_MAX, 0);
host = gethostname(&test[0], test.length());
int testSize = test.length();
An std::string object can contain NULs (i.e. '\0' characters). You are storing the name in the first bytes of a string object that was created with a size of HOST_NAME_MAX length.
Storing something in the beginning of the string data won't change the length of the string that remains therefore HOST_NAME_MAX.
When creating a string from a char pointer instead the std::string object created will contain up to, but excluding, the first NUL character (0x00). The reason is that a C string cannot contain NULs because the first NUL is used to mark the end of the string.
Consider what you're doing in each case. In the former code snippet, you're declaring a character array capable of holding HOST_NAME_MAX-1 characters (1 for the null terminator). You then load some string data into that buffer via the call to gethostname and then print out the length of buffer by assigning it to a std::string object using std::string::operator= that takes a const char *. One of the effects of this is that it will change an internal size variable of std::string to be strlen of the buffer, which is not necessarily the same as HOST_NAME_MAX. A call to std::string::length simply returns that variable.
In the latter case, you're using the std::string constructor that takes a size and initial character to construct test. This constructor sets the internal size variable to whatever size you passed in, which is HOST_NAME_MAX. The fact that you then copy in some data to std::strings internal buffer has no bearing on its size variable. As with the other case, a call to the length() member function simply returns the size - which is HOST_NAME_MAX - regardless of whether or not the actual length of the underlying buffer is smaller than HOST_NAME_MAX.
As #MattMcNabb mentioned in the comments, you could fix this by:
test.resize( strlen(test.c_str()) );
Why might you want to do this? Consistency with the char buffer approach might be a reason, but another reason may be performance oriented. In the latter case you're not only outright setting the length of the string to HOST_NAME_MAX, but also its capacity (omitting the SSO for brevity), which you can find starting on line 242 of libstdc++'s std::string implementation. What this means in terms of performance is that even though only, say, 25 characters are actually in your test string, the next time you append to that string (via +=,std::string::append,etc), it's more than likely to have to reallocate and grow the string, as shown here, because the internal size and internal capacity are equal. Following #MattMcNabb's suggestion, however, the string's internal size is reduced down to the length of the actual payload, while keeping the capacity the same as before, and you avoid the almost immediate re-growth and re-copy of the string, as shown here.
After using strcpy source is getting corrupted and getting correct destination. Following is my code please suggest me why my source is getting corrupted? If i keep a fixed size to second character array q[] then my source is not being changed. Why is this strange behaviour. -
I am using MSVC 2005
void function(char* str1,char* str2);
void main()
{
char p[]="Hello world";
char q[]="";
function(p,q);
cout<<"after function calling..."<<endl;
cout<<"string1:"<<"\t"<<p<<endl;
cout<<"string2:"<<"\t"<<q<<endl;
cin.get();
}
void function(char* str1, char* str2)
{
strcpy(str2,str1);
}
OUTPUT:
after function calling...
string1: ld
string2: Hello world
Thanks in advance,
Malathi
strcpy does not allocate memory required to store the string.
You must allocate enough memory in str2 before you do the strcpy.
Otherwise, you get undefined behaviour as you are overwriting some non-allocated memory.
q has only space for 1 character which is the terminating \0.
Please read a book about C - you need to learn something about memory management.
Most likely your memory looks like this (simplified): Qpppppppppppp. So when you strcpy to q, you will overwrite parts of p's memory.
Since you are using C++: Simply use std::string and or std::stringstream instead of raw char arrays.
In your code, q, is an one-element array (basing on the length of "", which is equal to one due to the null terminator), so it cannot contain the whole string. Hence you can't do a strcpy because it writes over invalid memory location (tries to write too much data to an array).
Declare q to be big enough to contain your string. Also, you can use strncpy to be on the safe side.
char q[] = ""; creates a character array with exactly 1 element - copying more data into it won't reserve more memory for it.
So, what happens is that when you write past the space reserved for q, you start overwriting what's in p - the two variables are next to each other in memory.
What everyone is saying is half correct. The code is failing because space is not reserved for the copy as others have pointed out correctly. The part that's missing is that your objects are on the stack, not the heap. Therefore it is not only likely, but inevitable that your code will get corrupted as the stack can no longer be unwound.
The array "q" is just one byte long; it definitely doesn't have room for the string "Hello, World"! When you try to copy "Hello, World" to q, you end up exceeding the bounds of q and overwriting p, which is adjacent to it on the stack. I imagine drawing a diagram of how these things are laid out on the stack, you could determine exactly why the garbage that ends up in p is just "ld".
strcpy expects you to provide an allocated storage buffer, not just a char* pointer. If you change char q[]=""; to char q[50]; it will work. Since you're only giving strcpy a pointer to a zero length string it doesn't have enough space to store the copied string and overwrites aka corrupts the memory.
I would appreciate for some C++ expertize advice on this please. I have a Char array
<unsigned char ch1[100];>
data (ASCII code) gets filled in this ( max 6 or 8 array spaces and rest is empty). I want to process valid bits in the array only either converting them to Hex or again Char array. I tried
<memcpy (ch1,ch2,sizeof(ch1))>
but all garbage values are also copied..... :(
<strcpy gives me an error>
also number of bytes copied are dynamic ( 1 time :- 4; 2 time :- 6.....)
Do you know how many valid bytes do you have in your array? If yes, you can pass that number in as the 3rd argument of memcpy.
Otherwise you can zero-initialize the array and use strcpy which will stop on the first zero:
char ch1[100];
// zero out the array so we'll know where to stop copying
memset(ch1, 0, sizeof(ch1));
... data gets filled here ....
strcpy (ch2, ch1);
// zero out array again so we'll catch the next characters that come in
memset(ch1, 0, sizeof(ch1));
... life goes on ...
So only copy the chars that are actually initialized. You as a programmer are responsible for tracking what's initialized and what's not.