Reputation: 190
Following code gives empty string and length = 0, but while debugging I can see the childDisplayName has correct name.
CHAR fileSystemName[MAX_PATH + 1] = { 0 };
DWORD serialNumber = 0; DWORD maxComponentLen = 0;
string childDisplayName = "";
DWORD fileSystemFlags = 0;
if (GetVolumeInformationA("C:\\", // L"\\MyServer\MyShare\"
(LPSTR)&childDisplayName, MAX_PATH+1,
&serialNumber, &maxComponentLen,
&fileSystemFlags, fileSystemName, sizeof(fileSystemName)) == true)
{
cout << childDisplayName << "length: "<<childDisplayName.length()<<endl;
}
following code works fine. I am not getting why LPSTR works when I pass char array and does not work when I pass a string.
CHAR fileSystemName[MAX_PATH + 1] = { 0 };
DWORD serialNumber = 0; DWORD maxComponentLen = 0;
CHAR childDisplayName[MAX_PATH + 1] = { 0 };
DWORD fileSystemFlags = 0;
if (GetVolumeInformationA("C:\\", // L"\\MyServer\MyShare\"
childDisplayName, MAX_PATH+1,
&serialNumber, &maxComponentLen,
&fileSystemFlags, fileSystemName, sizeof(fileSystemName)) == true)
{
cout << childDisplayName << "length: "<<strlen(childDisplayName)<<endl;
}
Upvotes: 0
Views: 448
Reputation: 3890
In first code snippet, I cannot get the correct name of childDisplayName.
Although it seems to have several characters, but an exception is triggered when I want to output it.
So you passed a wrong address to the GetVolumeInformationA
.Because the address of a string is not the address of the characters
You can test like the following code:
string s("test");
CHAR cs[] = "test";
cout << (void*)&s << endl;
cout << (void*)&s[0] << endl;
cout << (void*)&cs << endl;
cout << (void*)&cs[0] << endl;
As @churill says, std::string
only manages a dynamic array of characters.So you can not pass the address of string to the function.
And according to MSDN:
If you modify the contents of the string returned by the const overload of data, the behavior is undefined. You also get undefined behavior if the terminal null character is changed to any other value. The returned pointer may be invalidated if a non-const reference to the string is passed to a standard library function. It can also be invalidated by a call to a non-const member function.
So even if you really succeed in passing childDisplayName.data()
into the function. This is also an undefined behavior.I recommend that you pass in the parameter types required by the function correctly, instead of trying to pass other undefined or untyped behaviors, which will cause you a lot of confusion.
Upvotes: 0
Reputation: 3973
string childDisplayName = "";
creates an empty empty string (zero size and unspecified capacity). Using that as a data-buffer to write into is not likely to go well.
You can do this: string childDisplayName(MAX_PATH + 1, ' ');
to create a string with the proper space allocated.
Secondly, as @churill wrote, the address of a string is not the address of the characters in it. Instead use childDisplayName.data()
to get a char*
to the internal storage of the string that you can write in - but make sure not to write outside the range [data(); data() + size())
.
EDIT: A bit on how std::string
and .data()
works.
I made a small example program:
#include<iostream>
#include<string>
void print(const std::string& s)
{
std::cout << "String size: " << s.size() << '\n';
std::cout << "String contents: >>" << s << "<<\n";
std::cout << "String as c-string: >>" << s.c_str() << "<<\n";
std::cout << '\n';
}
int main() {
std::string bla = "";
auto bladata = bla.data();
for (int i = 0;i < 5;++i) {
bladata[i] = '!';
}
print(bla);
std::string bla2(10, '\0');
auto bla2data = bla2.data();
for (int i = 0;i < 5;++i) {
bla2data[i] = '!';
}
print(bla2);
}
When run this outputs:
String size: 0
String contents: >><<
String as c-string: >>!!!!!╠╠╠╠╠╠╠╠╠╠╠<<
String size: 10
String contents: >>!!!!! <<
String as c-string: >>!!!!!<<
What is going on here? First thing to notice is that an empty std::string
is created with zero size and unspecified capacity - looking in my debugger, I know that on my system that unspecified capacity is 15, so as long as I don't go beyond that nothing should crash. But this is obviously not something you should do in real code (writing here is strictly undefined behavior).
This means that the bla
string is size 0, and contains a 15 character char buffer, where I set the first 5 characters to '!'. So when I try to print its size()
or print it as a std::string
it is identical to any regular empty string. However, if I use .c_str()
to print the internal buffer directly, then it prints as any old char*
and just prints whatever is in memory until it encounters a null-character.
On the other hand, bla2
is initialized to contain 10 null-characters. That means that its size is 10, and its capacity is at least 10 (in my case it happens to also be 15). This means that after the loop it still reports as size 10, regardless of how many '!'s I put into the buffer, and when I print it as a std::string
it prints all the 10 characters it contains; both the 5 '!'s and the 5 '\0's. However, when I print it as a char*
it prints the 5 '!'s and then stop as soon as it encounters a null-character.
Upvotes: 1