I have the below piece of code where I'm unable to figure out why I'm getting some weird symbols at the end of the buffer.
char value[100];
if(getxattr(filename, "user.permission", value, sizeof(value))!=-1){
//strncpy(val, value, strlen(value));
printf("value is %s\n", value);
}
For length >4 elements, it prints properly but if the value has less than four elements it appends some random characters at the end.
When I print the size of the value, it shows 6 for any value length between 1-4.
Please, someone, explain why is this behavior.
You have to honour the real size of the attribute.
The call getxattr() returns the size of the value. So the following would be correct:
ssize_t sz = getxattr(filename, "user.permission", value, sizeof(value)-1);
if (sz != -1) {
value[sz] = '\0';
printf("value is %s\n", value);
}
It looks, like your value is a string, but it is not null terminated, you have to do that yourself. So, getxattr() is not appending random bytes, the char array is simply not initialized and it is not completely overwritten, so some uninitialized bytes remain there.
From documentation (emphasize mine):
getxattr() retrieves the value of the extended attribute identified
by name and associated with the given path in the filesystem. The
attribute value is placed in the buffer pointed to by value; size
specifies the size of that buffer. The return value of the call is
the number of bytes placed in value.
I didnt find something about getxattr() placing a \0 so I would expect that you have to use the size returned from the function to know the size of the string.
Related
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
}
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.
In my program, I have a char array (char data[]) from which i have to extract the data and store it in an integer variable(value). To do so, I have used atoi in my program. Problem is that I sometime receive null in the char array(data). If i use atoi on this value, I get the value 0 in integer variable instead of (null)
The real function is quite big and I cannot post the entire code here. From function mentioned below, I hope you guys will get some idea about what I am doing here.
Get_Data(char data[])
{
int value;
value = atoi(p);
}
I recently read that we should use strtol instead of atoi. I tried that too. but I am still getting 0 in variable value.
I want to know which function should i use so that i get (null) in integer variable value?
By null, I mean empty character array here
Please provide solutions specific to the problem. In the above function, if data gets empty char value, how do i make sure that my int variable value also gets empty value and not zero??
atoi return zero for
If the first sequence of non-whitespace characters in str is not a
valid integral number, or if no such sequence exists because either
str is empty or it contains only whitespace characters, no conversion
is performed and zero is returned.
Also you requrement for returning NULL is not possible because you assign those value in int and int can't hold not NULL.
Because atoi tries to read as much as it can.
You should use strtol instead , like this:
char* endptr = NULL
char* myString = "OUPS";
long n = strtol(myString, &endptr, 10);
if (*endptr != '\0') {
// ERROR
}
Read the reference link for more explanation (and example too).
Isn't that good?
There is no Integer value in C++ spelled as null
NULL in an integer form is 0 only.
char value[255];
DWORD BufferSize = 8192;
RegGetValue(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", L"ProductName", RRF_RT_ANY, NULL, &value, &BufferSize);
cout << value;
After RegKeyValue() runs, it appears that value is
value 0x0034f50c "ÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌ... char[255]
What's going on here?
Note: RegKeyValue() returns 0
There are two issues here.
Make sure the return value of RegGetValue is ERROR_SUCCESS. If it is not, the routine failed. Also, you can check to see what was written into BufferSize, as RegGetValue specifies the number of bytes written.
You're passing in a buffer defined as char value[255];, then specifying it's length as 8192. This can cause a buffer overrun.
You didn't check the return value of RegGetValue. Most likely the call failed and the buffer value was never assigned anything. Always check return values.
From the code we can see, I note that you are lying about the buffer size. You say that it is 8192 bytes. But you only allocated 255 bytes. You are also calling the Unicode version of the API, but passing in a char buffer. If you are expecting string data then you need to supply a buffer of wide characters. The Unicode version of this API will return string data as UTF-16 encoded text.
Once you get all that sorted you next need to check what type is stored in that value. You are passing NULL for the type parameter. Pass a pointer to a variable and find out whether or not a string really is stored
there. You will also need to read how many bytes are read and set the null-terminator in your buffer accordingly.
I like "reinventing the wheel" for learning purposes, so I'm working on a container class for strings. Will using the NULL character as an array terminator (i.e., the last value in the array will be NULL) cause interference with the null-terminated strings?
I think it would only be an issue if an empty string is added, but I might be missing something.
EDIT: This is in C++.
"" is the empty string in C and C++, not NULL. Note that "" has exactly one element (instead of zero), meaning it is equivalent to {'\0'} as an array of char.
char const *notastring = NULL;
char const *emptystring = "";
emptystring[0] == '\0'; // true
notastring[0] == '\0'; // crashes
No, it won't, because you won't be storing in an array of char, you'll be storing in an array of char*.
char const* strings[] = {
"WTF"
, "Am"
, "I"
, "Using"
, "Char"
, "Arrays?!"
, 0
};
It depends on what kind of string you're storing.
If you're storing C-style strings, which are basically just pointers to character arrays (char*), there's a difference between a NULL pointer value, and an empty string. The former means the pointer is ‘empty’, the latter means the pointer points to an array that contains a single item with character value 0 ('\0'). So the pointer still has a value, and testing it (if (foo[3])) will work as expected.
If what you're storing are C++ standard library strings of type string, then there is no NULL value. That's because there is no pointer, and the string type is treated as a single value. (Whereas a pointer is technically not, but can be seen as a reference.)
I think you are confused. While C-strings are "null terminated", there is no "NULL" character. NULL is a name for a null pointer. The terminator for a C-string is a null character, i.e. a byte with a value of zero. In ASCII, this byte is (somewhat confusingly) named NUL.
Suppose your class contains an array of char that is used to store the string data. You do not need to "mark the end of the array"; the array has a specific size that is set at compile-time. You do need to know how much of that space is actually being used; the null-terminator on the string data accomplishes that for you - but you can get better performance by actually remembering the length. Also, a "string" class with a statically-sized char buffer is not very useful at all, because that buffer size is an upper limit on the length of strings you can have.
So a better string class would contain a pointer of type char*, which points to a dynamically allocated (via new[]) array of char s. Again, it makes no sense to "mark the end of the array", but you will want to remember both the length of the string (i.e. the amount of space being used) and the size of the allocation (i.e. the amount of space that may be used before you have to re-allocate).
When you are copying from std::string, use the iterators begin(), end() and you don't have to worry about the NULL - in reality, the NULL is only present if you call c_str() (in which case the block of memory this points to will have a NULL to terminate the string.) If you want to memcpy use the data() method.
Why don't you follow the pattern used by vector - store the number of elements within your container class, then you know always how many values there are in it:
vector<string> myVector;
size_t elements(myVector.size());
Instantiating a string with x where const char* x = 0; can be problematic. See this code in Visual C++ STL that gets called when you do this:
_Myt& assign(const _Elem *_Ptr)
{ // assign [_Ptr, <null>)
_DEBUG_POINTER(_Ptr);
return (assign(_Ptr, _Traits::length(_Ptr)));
}
static size_t __CLRCALL_OR_CDECL length(const _Elem *_First)
{ // find length of null-terminated string
return (_CSTD strlen(_First));
}
#include "Maxmp_crafts_fine_wheels.h"
MaxpmContaner maxpm;
maxpm.add("Hello");
maxpm.add(""); // uh oh, adding an empty string; should I worry?
maxpm.add(0);
At this point, as a user of MaxpmContainer who had not read your documentation, I would expect the following:
strcmp(maxpm[0],"Hello") == 0;
*maxpm[1] == 0;
maxpm[2] == 0;
Interference between the zero terminator at position two and the empty string at position one is avoided by means of the "interpret this as a memory address" operator *. Position one will not be zero; it will be an integer, which if you interpret it as a memory address, will turn out to be zero. Position two will be zero, which, if you interpret it as a memory address, will turn out to be an abrupt disorderly exit from your program.