Where does the pointer returned by calling string::c_str() point to ? In the following code snippet, I thought I will give get a segmentation fault but it gives me the correct output. If the pointer returned by string::c_str() points to an internal location inside the string object, then when the function returns and the object destructor gets invoked, I should get an invalid memory access.
#include <iostream>
#include <string>
using namespace std;
const char* func()
{
string str("test");
return str.c_str();
}
int main()
{
const char* p = func();
cout << p << endl;
return 0;
}
Output: test
Compiler: g++ 4.3.3
Platform: ubuntu 2.6.28-19
Where does the pointer returned by calling string::c_str() point to?
It points to some place in memory where a null-terminated string containing the contents of the std::string is located.
The pointer is only valid until the std::string is modified or destroyed. It is also potentially invalidated if you call c_str() or data() again.
Basically, your safest bet is to assume the pointer obtained from c_str() is invalidated the next time you do something to the std::string object.
I should get an invalid memory access.
No, you get undefined behavior. You might get a memory access error of some kind (like a segmentation fault), but your program also might appear to continue running correctly. It might appear to work one time you run your program but fail the next.
What would you expect this to print out?
#include <iostream>
#include <string>
int main()
{
int* test = new int[20];
test[15] = 5;
std::cout << test[15] << "\n";
delete[] test;
std::cout << test[15] << "\n";
return 0;
}
In release mode on VS 2010, I get this result:
5
5
Deallocated memory doesn't necessarily throw an exception when you try to access it. The value doesn't necessarily get re-written, either. (Interestingly enough, if I change the compile to debug mode, the compiler overwrites the value with -572662307).
What happens when you try to access it is undefined by the standard. That means the compiler can do whatever it feels like doing, or choose to do nothing. (Or crash your program, or blow up the universe...)
Related
How variable int a is in existence without object creation? It is not of static type also.
#include <iostream>
using namespace std;
class Data
{
public:
int a;
void print() { cout << "a is " << a << endl; }
};
int main()
{
Data *cp;
int Data::*ptr = &Data::a;
cp->*ptr = 5;
cp->print();
}
Your code shows some undefined behavior, let's go through it:
Data *cp;
Creates a pointer on the stack, though, does not initialize it. On it's own not a problem, though, it should be initialized at some point. Right now, it can contain 0x0badc0de for all we know.
int Data::*ptr=&Data::a;
Nothing wrong with this, it simply creates a pointer to a member.
cp->*ptr=5;
Very dangerous code, you are now using cp without it being initialized. In the best case, this crashes your program. You are now assigning 5 to the memory pointed to by cp. As this was not initialized, you are writing somewhere in the memory space. This can include in the best case: memory you don't own, memory without write access. In both cases, your program can crash. In the worst case, this actually writes to memory that you do own, resulting in corruption of data.
cp->print();
Less dangerous, still undefined, so will read the memory. If you reach this statement, the memory is most likely allocated to your program and this will print 5.
It becomes worse
This program might actually just work, you might be able to execute it because your compiler has optimized it. It noticed you did a write, followed by a read, after which the memory is ignored. So, it could actually optimize your program to: cout << "a is "<< 5 <<endl;, which is totally defined.
So if this actually, for some unknown reason, would work, you have a bug in your program which in time will corrupt or crash your program.
Please write the following instead:
int main()
{
int stackStorage = 0;
Data *cp = &stackStorage;
int Data::*ptr=&Data::a;
cp->*ptr=5;
cp->print();
}
I'd like to add a bit more on the types used in this example.
int Data::*ptr=&Data::a;
For me, ptr is a pointer to int member of Data. Data::a is not an instance, so the address operator returns the offset of a in Data, typically 0.
cp->*ptr=5;
This dereferences cp, a pointer to Data, and applies the offset stored in ptr, namely 0, i.e., a;
So the two lines
int Data::*ptr=&Data::a;
cp->*ptr=5;
are just an obfuscated way of writing
cp->a = 5;
I am pretty new to C++, and while getting started I got stuck on a frustrating problem concerning pointers. Consider the following code:
#include <iostream>
using namespace std;
int main (){
int* mypointer;
*mypointer = 1;
cout << "Whats wrong";
}
It crashes during runtime. I suspect it has to do with the pointer assignment. But after commenting out the cout statement, the program executes. By assigning the pointer as
int* mypointer, myvar;
myvar = 1;
mypointer = &myvar;
the program runs, and I can print the value of the pointer as:
cout << "value of pointer: " << *mypointer;
I draw the conclusion that this would be the correct usage of a pointer.
BUT: Why does the following code execute??:
#include <iostream>
#include <stdio.h>
using namespace std;
int main (){
int* mypointer;
*mypointer = 1;
printf("This works!\n");
printf("I can even print the value mypointer is pointing to: %i",*mypointer);
}
Simply using printf?? I would really appreciate an explanation guys!
The code executes because, just by chance, your compiler has managed to optimise the program down enough that the 1 is "hardcoded" into the printf call.
It would probably have done this anyway, rendering both the original int and the pointer irrelevant, but in this instance it's not reflecting the fact that the pointer was broken and there wasn't an original int.
so, strictly speaking, this doesn't even reflect the semantics of the program: as you've spotted, assigning a value to an int that doesn't exist (through an uninitialised or otherwise invalid pointer) is nonsense and results in undefined behaviour.
But that's the nature of undefined behaviour: anything can happen! The authors of your compiler are making the most of that, by realising that they don't have to write any code to make this case work logically. Because it's you who violated the C++ contract. :)
Below c++ program works fine, even though i have not allocated any memory to chr.
I went through google, SO and came across this
Why does this intentionally incorrect use of strcpy not fail horribly?
Here the program works fine for destination which has space less than the source.
Does that apply in my case also,strcpy writes into a random location in the heap?
#include<iostream>
using namespace std;
class Mystring
{
char *chr;
int a;
public:
Mystring(){}
Mystring(char *str,int i);
void Display();
};
Mystring::Mystring(char *str, int i)
{
strcpy(chr,str);
a = i;
}
void Mystring::Display()
{
cout<<chr<<endl;
cout<<a<<endl;
}
int main()
{
Mystring a("Hello world",10);
a.Display();
return 0;
}
output:-
Hello world
10
I tried the same thing with another c++ program, with any class and class member, and i was able to see the crash.
#include<iostream>
using namespace std;
int main()
{
char *src = "Hello world";
char *dst;
strcpy(dst,src);
cout<<dst<<endl;
return 0;
}
Please help me understand the behavior in the first c++ program.Is memory allocated somehow or strcpy is writing to some random memory location.
The behavior of your program is undefined by the C++ standard.
This means that any C++ implementation (e.g. a compiler) can do whatever it wants. Printing "hello!" on stdout would be a possible outcome. Formatting the hard disk would still be acceptable, as far as the C++ standard is involved. Practically, though, some random memory on the heap will be overwritten, with unpredictable consequences.
Note that the program is even allowed to behave as expected. For now. Unless it's Friday. Or until you modify something completely unrelated. This is what happened in your case, and is one of the worst thing to happen from the point of view of a programmer.
Later on, you may add some code and see your program crash horribly, and think the problem lies in the code you just added. This can cause you to spend a long time debugging the wrong part of the code. If that ever happens, welcome to hell.
Because of this, you should never, ever, rely on undefined behavior.
strcpy() is indeed writing to a random location.
And it's a blind luck if your program runs fine and nothing crashes.
You have created on object of MyString class on a stack. In that object there's a member pointer chr, which points to some arbitrary location. Does your constructor take care to initialize that pointer or allocate a memory for the pointer to point at? -- No, it doesn't. So chr points somewhere.
strcpy() in its turn doesn't care about any pointer validity, it trusts your professionalism to provide valid input. So it does its job copying stings. Luckily, overwriting memory at the location pointed by an uninitialized chr doesn't crash you program, but that's "luckily" only.
It is known that strcpy() can cause overflow errors, because there is no check made wherever the data will fit in the new array or not.
The outcome of this overflow may sometime never been noticed, it all depends on where the data is written. However a common outcome is heap and/or program corruption.
A safe alternative of strcpy() is the usage of strcpy_s() that requires also the size of the array. You can read more about the usage of strcpy_s() on MSDN or here
Actually, strcpy() does something like this:
char *strcpy(char *dest, const char *src)
{
unsigned i;
for (i=0; src[i] != '\0'; ++i)
dest[i] = src[i];
dest[i] = '\0';
return dest;
}
So, when you pass a pointer to some character array to strcpy, it copies data from src to dest until it reaches NULL terminated character.
Character pointer does not contain any information about length of string, so when you pass dest pointer, it copies data even though you haven't assigned memory to it.
Run this example code, you will get my point:
#include <cstring>
#include <iostream>
using namespace std;
int main()
{
char str1[] = "Hello_World!";
char str2[5];
char str3[10];
strcpy(str2,str1);
cout << "string 1:" << str1 << endl;
cout << "string 2:" << str2 << endl;
cout << "string 3:" << str3 << endl;
return 0;
}
This will not show any error but you can understand by my example that this is not a good practice.
I am new to C++ and ran into following supposedly bug, but somehow my program just works..
Here is the code
#include<iostream>
#include<queue>
#include <string>
int main()
{
string s ("cat");
queue<string> _queue;
_queue.push(s);
string & s1 = _queue.front();
_queue.pop();
// at this time s1 should become invalid as pop called destructor on s
std::cout << s1 << std::endl;
return 0;
}
It just works, even though s1 is a reference to an invalid object. Is there a way i can assert that s1 truely refers to an invalid object?
Trying to access a destroyed object the way you do it in your code results in undefined behavior. And no, there's no language-provided way to perform a run-time check for this situation. It is entirely your responsibility to make sure things like that do not happen in your code.
The fact that "it just works" in your experiment is just an accident (with certain degree of typical computer determinism, as usual). Something completely unrelated might change in your program, and this code will no longer "work".
Why can this code run successfully in Code::block. The IDB just reports
warning: "reference to local variable ‘tmp’ returned",
but ouput the result "hello world" successfully.
#include <iostream>
#include<string>
using namespace std;
const string &getString(const string &s)
{
string tmp = s;
return tmp;
}
int main()
{
string a;
cout<<getString("hello world")<<endl;
return 0;
}
Upon leaving a function, all local variables are destroyed. By returning a reference to tmp, you are returning a reference to an object that soon ceases to exist (that is, technically, the address of a memory region whose contents are no longer meaningful).
Accessing such a dangling reference invokes what is called 'undefined behaviour' - and sadly, 'work as usual' is one kind of 'undefined behaviour'. What might happen here is that std::string keeps a small static buffer for small strings (as opposed to large strings, for which it grabs memory from the heap), and upon leaving getString the stack space occupied by this string is not zeroed so it still seems to work.
If you try a debug build, or invoke another function in between (which will effectively overwrite the stack space), it won't work anymore.
You are causing an undefined behaviour. The standard doesn't tell what happens in that case, however your compiler detected it.
tmp disappears the moment you return from getString. Using the returned reference is undefined behaviour, so anything can happen.
To fix your code, return the string by value:
string getString(const string &s)
{
...
Are you sure? It should segfault (it will with gcc on most platforms). That code does contain an error, and if you get 'lucky' and it works, then you're brushing a nasty bug under the carpet.
Your string is returned by reference, that is, rather than making a new string which is valid in the context you are returning into, a pointer to a stale, destructed, object is being returned, which is bad. const string getString... will do as the declaration for the function's return type.
The temporary object is deallocated, however its contents are still there on the stack, until something rewrites it. Try to call a few functions between calling your function and printing out the returned object:
const string& garbage = getString("Hello World!");
callSomeFunctionThatUsesALotOfStackMemory();
cout<< garbage << endl;
As you can see the below example code is just slightly modified by calling goodByeString(). Like the other answers already pointed out the variable in getString called tmp is local. the variable gets out of scope as soon as the function returns. since it is stack allocated the memory is still valid when the function returns, but as soon as the stack grows again this portion of memory where tmp resided gets rewritten with something else. Then the reference to a contains garbage.
However if you decide to output b since it isn't returned by reference the contents is still valid.
#include <iostream>
#include<string>
using namespace std;
const string &getString(const string &s)
{
string tmp = s;
return tmp;
}
string goodByeString(const string &s)
{
string tmp = "lala";
tmp += s;
return tmp;
}
int main()
{
const string &a = getString("Hello World!\n");
string b = goodByeString("ciao\n");
cout << a << endl;
return 0;
}