string allocation in C++: why does this work? [duplicate] - c++

This question already has answers here:
Can a local variable's memory be accessed outside its scope?
(20 answers)
Closed 6 years ago.
void changeString(const char* &s){
std::string str(s);
str.replace(0, 5, "Howdy");
s = str.c_str();
}
int main() {
const char *s = "Hello, world!";
changeString(s);
std::cout << s << "\n";
return 0;
}
When I run this code, it prints "Howdy, world!" I would think that str gets destroyed when changeString exits. Am I missing something with the way std::string gets allocated?

Yes, str is destroyed; but the memory of the string isn't cleared; your "s" pointer point to a free but non cleared memory. Very dangerous.

It's undefined behaviour when std::cout << s tries to access the pointer, because the destructor of the local std::string in changeString has freed the memory which the pointer still points to.
Your compiler is not required to diagnose the error but can instead generate a binary which can then do whatever it wants to.
The fact that you got the desired output was just bad luck because it made you think that your code was correct. For instance, I've just compiled your code on my machine and got empty output instead. It could also have crashed, or it may have done other, unrelated things.

Related

Why does this results in a segmentation fault? [duplicate]

This question already has answers here:
can't modify char* - Memory access violation
(4 answers)
Closed 2 years ago.
int main()
{
char *p = "I like C++";
strcpy(p, "John Smith");
std::cout << p << std::endl;
EXIT_SUCCESS;
}
As the title stated, why does this results in segmentation fault
Speaking in the terms used by strcpy() documentation, you are trying to copy "John Smith" (the source argument) into p (the destination argument).
Although p is a pointer of type char *, it resides in the read-only data section (.rodata probably).
Trying to copy a new string into it, means trying to write over read-only memory.
Changing the declaration to char p[] = "I like C++"; fixes the issue as p now resides on the stach which is both readable and writeable memory.
By the way, the last line is missing a return and should be return EXIT_SUCCESS.

Wchar_t empty unless "wcout" used [duplicate]

This question already has answers here:
Can a local variable's memory be accessed outside its scope?
(20 answers)
How to return local array in C++?
(12 answers)
Closed 7 years ago.
Ill start with an example of source code (that i modified for clarity so ignore variables like "someLetter"):
wchar_t *someFunction()
{
wchar_t str[1024] = L"";
for (int i = 0; i < 50; i++)
{
str[i] = someLetter;
}
str[51] = L'\0';
return str;
}
The above code simply adds wchars to w_char array and when for loop is ended, it ends the array with L'\0'. Variable ret should hold the string.
However, when I execute the code below, i get nothing (empty string).
wchar_t *result = someFunction();
wcout << result << endl;
This is where it gets weird. If i execute the code mentioned all above, I get nothing. BUT if I add wcout << str << endl; in someFunction(), everything seems to be working fine i.e. code below does what its supposed to do.
wchar_t *result = someFunction();
wcout << result << endl;
TL:DR
Code below doesnt print out "result". Instead it prints out nothing and result is blank. The problem is fixed if I add wcout << str<< endl; to someFunction(). Why is that and how can I avoid that.
wchar_t *result = someFunction();
wcout << result << endl;
You are returning a pointer to automatic storage that goes out of scope when someFunction ends, so there is no correct behavior; it is undefined what will happen if you access a variable after it's gone out of scope. If you really need to return a wchar_t*, you'll need to either use a static array, pass a pointer to a buffer into someFunction, or dynamically allocate memory (and make the caller responsible for freeing that memory). The best thing to do would probably be to use std::wstring instead of raw wchar_t*s.
This code cannot work as you return the address of a local variable. The memory of wchar_t str[1024] is freed until someFunction() returns to the caller.
Sidenode: It should be str[50] = L'\0'; and not str[51] = L'\0'
To get you code working you might either use a std::wstring and return a copy of it or allocate the memory for str on the heap using new[] and delete[] it later on.
You should probably get a bit more familiar with C++ before asking questions like this.

Why reference to a local variable is still valid [duplicate]

This question already has answers here:
Can a local variable's memory be accessed outside its scope?
(20 answers)
Closed 7 years ago.
I am running following simple program in C++ program:
#include <iostream>
using namespace std;
string& ShowString()
{
string s1 = "abcd";
return s1;
}
int main()
{
string s2 = ShowString();
cout << s2 << endl;
return 0;
}
and the output is: abcd
The problem is that function ShowString returns a reference to a local variable and by the time that program reaches to cout << s2 << endl, s1 should have been destroyed (and also s2). But the output is still correct, which brings me to the conclusion that although s1 no longer exists, its contents in stack memory are still valid (probably until something else overwrites it).
I appreciate if you could let me know whether this conclusion is correct.
Thanks
Because it is an Undefined Behaviour. You can't trust that value.

How does std::string keep memory beyond scope without a leak? [duplicate]

This question already has answers here:
Can a local variable's memory be accessed outside its scope?
(20 answers)
Closed 7 years ago.
My question is about the following simple code:
#include <iostream>
using namespace std;
const char* call()
{
string str("Hey there.");
return str.c_str();
}
int main()
{
const char* blah = call();
cout << blah << endl;
system("pause");
return 0;
}
Output:
"Hey there."
Now, how is it that the memory holding "Hey there." isn't destroyed or causing a memory leak when std::string is destroyed at the end of the method? I'm not a c++ expert but i believe if the string allocated memory holding "Hey there." on the stack, it would be deleted when the string goes out of scope (end of method), and if the string allocated memory on the heap to store "Hey there." then this would cause a memory leak since its clearly not destroying the memory because we are accessing the memory after the string has gone out of scope.
So, how is it that i am able to access the memory blocks pointed to by c_str() without causing a memory leak?
Thank you and much appreciated responses.
I believe your string is technically out of scope but it does not get 'deleted' from memory immediately. It needs to get overwritten. When a variable goes out of scope, the machine does not guarantee it will still be valid, but by chance, it could. When you de-reference a pointer, there's a chance that the old string information is still there in that location in memory. Also the term 'memory leak' is reserved only for dynamic allocation of memory using the keyword new for when you lose the last pointer to that data which means you have lost access to that data.

initializing char array in a function and returning it causes wrong outputs in main [duplicate]

This question already has answers here:
Can a local variable's memory be accessed outside its scope?
(20 answers)
Closed 8 years ago.
char* func()
{
const int size = 24;
char bin[size];
char *temp;
for(int i=0; i<23; i++)
bin[i] = '1';
bin[23] = '\0';
temp = bin;
return temp;
}
int main()
{
char *s;
s = func();
cout << s << endl; //prints out weird values
return 0;
}
When compiled and ran, it print random values. In the function func, I initialized a char array and tried to return it. Upon returning it and printing it in main, it prints out weird values. What is wrong? Any help would be appreciated.
char bin[size];
allocate memory on the stack, you cannot refer to that location after the function returns: "char *s" is assigned a value that refer to an invalid memory location.
You must not use pointers to freed space, like the stack of a function which has finished executing.
This Undefined Behavior means anything goes, even the proverbial demons flying out of your nose.
Your choices:
Use a caller-allocated buffer.
Use a static buffer (beware reentrancy problems and multithreading woes).
Use dynamic allocation (new, new[], malloc() and friends).
return a struct (standard container or otherwise) containing the data. Might use dynamic allocation. (Last point courtesy of Matt McNabb).