I'm trying to get segment fault, but I can't get it and I wonder why.
#include <iostream>
using namespace std;
class A{
public:
char *field_;
A(char *field):field_(field) {
// I believe(suppose) that it's equal to
// field_ = field;
// so actual initial string wasn't copied, only a pointer to it
}
void show() {
cout<<field_<<"\n";
}
};
int main(){
A *obj;
{
char *line="I should be freed";
obj = new (nothrow) A(line);
}
// After exiting from the previous scope,
// char *line variable should be freed.
// Constructor of class A didn't make byte for byte
//copying, so we cannot have
// access to it for sure
for(int i=0;i<4;i++) // trying to clear stack and erase char *line variable
char something[10000];
obj->show(); // and it works correctly!!!! why?
delete obj;
return 0;
}
Ok, as I understand it works correctly only because that string wasn't freed from memory.
I.e. we are just lucky.
And here we have undefined behaviour. Am I right?
Thank you in advance!!
You won't get a segmentation fault because there are no invalid memory references made by your program. I'd guess you think that ""I should be freed" is created on stack and then destroyed or freed somehow, and that is a wrong assumption because that is a constant string literal and it is placed into program data segment and is "alive" for the life of your program.
And even if it was allocated dynamically and freed automatically upon leaving the scope, you still cannot expect your program to receive SIGSEGV in that case. Because undefined behavior does not always result in segmentation faults.
Also, try to never write char *data = "blah-blah";. String literals are assumed to always be constant and trying to modify them is undefined behavior. Though people still hack around this sometimes.
char *line = "I should be freed";
You still see the content because the string literals has static storage duration. Here the string literal I should be freed resides in read only location and is freed once the program execution completes.
The program has no undefined behavior.
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;
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 sorry if I may not have phrased the question correctly, but in the following code:
int main() {
char* a=new char[5];
a="2222";
a[7]='f'; //Error thrown here
cout<<a;
}
If we try to access a[7] in the program, we get an error because we haven't been assigned a[7].
But if I do the same thing in a class :
class str
{
public:
char* a;
str(char *s) {
a=new char[5];
strcpy(a,s);
}
};
int main()
{
str s("ssss");
s.a[4]='f';s.a[5]='f';s.a[6]='f';s.a[7]='f';
cout<<s.a<<endl;
return 0;
}
The code works, printing the characters "abcdfff".
How are we able to access a[7], etc in the code when we have only allocated char[5] to a while we were not able to do so in the first program?
In your first case, you have an error:
int main()
{
char* a=new char[5]; // declare a dynamic char array of size 5
a="2222"; // assign the pointer to a string literal "2222" - MEMORY LEAK HERE
a[7]='f'; // accessing array out of bounds!
// ...
}
You are creating a memory leak and then asking why undefined behavior is undefined.
Your second example is asking, again, why undefined behavior is undefined.
As others have said, it's undefined behavior. When you write to memory out of bounds of the allocated memory for the pointer, several things can happen
You overwrite an allocated, but unused and so far unimportant location
You overwrite a memory location that stores something important for your program, which will lead to errors because you've corrupted your own memory at that point
You overwrite a memory location that you aren't allowed to access (something out of your program's memory space) and the OS freaks out, causing an error like "AccessViolation" or something
For your specific examples, where the memory is allocated is based on how the variable is defined and what other memory has to be allocated for your program to run. This may impact the probability of getting one error or another, or not getting an error at all. BUT, whether or not you see an error, you shouldn't access memory locations out of your allocated memory space because like others have said, it's undefined and you will get non-deterministic behavior mixed with errors.
int main() {
char* a=new char[5];
a="2222";
a[7]='f'; //Error thrown here
cout<<a;
}
If we try to access a[7] in the program, we get an error because we
haven't been assigned a[7].
No, you get a memory error from accessing memory that is write-protected, because a is pointing to the write-only memory of "2222", and by chance two bytes after the end of that string is ALSO write-protected. If you used the same strcpy as you use in the class str, the memory access would overwrite some "random" data after the allocated memory which is quite possibly NOT going to fail in the same way.
It is indeed invalid (undefined behaviour) to access memory outside of the memory you have allocated. The compiler, C and C++ runtime library and OS that your code is produced with and running on top of is not guaranteed to detect all such things (because it can be quite time-consuming to check every single operation that accesses memory). But it's guaranteed to be "wrong" to access memory outside of what has been allocated - it just isn't always detected.
As mentioned in other answers, accessing memory past the end of an array is undefined behavior, i.e. you don't know what will happen. If you are lucky, the program crashes; if not, the program continues as if nothing was wrong.
C and C++ do not perform bounds checks on (simple) arrays for performance reasons.
The syntax a[7] simply means go to memory position X + sizeof(a[0]), where X is the address where a starts to be stored, and read/write. If you try to read/write within the memory that you have reserved, everything is fine; if outside, nobody knows what happens (see the answer from #reblace).
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;
}
I've written a program that allocates a new object of the class T like this:
T* obj = new T(tid);
where tid is an int
Somewhere else in my code, I'm trying to release the object I've allocated, which is inside a vector, using:
delete(myVec[i]);
and then:
myVec[i] = NULL;
Sometimes it passes without any errors, and in some cases it causes a crash—a segmentation fault.
I've checked before calling delete, and that object is there—I haven't deleted it elsewhere before.
What can cause this crash?
This is my code for inserting objects of the type T to the vector:
_myVec is global
int add() {
int tid = _myVec.size();
T* newT = new T (tid);
if (newT == NULL){
return ERR_CODE;
}
_myVec.push_back(newT);
// _myVec.push_back(new T (tid));
return tid;
}
as it is - the program sometimes crash.
When I replace the push_back line with the commented line, and leave the rest as it is-it works.
but when I replace this code with:
int add() {
int tid = _myVec.size();
if (newT == NULL){
return ERR_CODE;
}
_myVec.push_back(new T (tid));
return tid;
}
it crashes in a different stage...
the newT in the second option is unused, and still - changes the whole process... what is going on here?
Segfaulting mean trying to manipulate a memory location that shouldn't be accessible to the application.
That means that your problem can come from three cases :
Trying to do something with a pointer that points to NULL;
Trying to do something with an uninitialized pointer;
Trying to do something with a pointer that pointed to a now deleted object;
1) is easy to check so I assume you already do it as you nullify the pointers in the vector. If you don't do checks, then do it before the delete call. That will point the case where you are trying to delete an object twice.
3) can't happen if you set NULL to the pointer in the vector.
2) might happen too. In you case, you're using a std::vector, right? Make sure that implicit manipulations of the vector (like reallocation of the internal buffer when not big enough anymore) doesn't corrupt your list.
So, first check that you delete NULL pointers (note that delete(NULL) will not throw! it's the standard and valid behaviour! ) - in your case you shouldn't get to the point to try to delete(NULL).
Then if it never happen, check that you're not having your vector fill with pointers pointing to trash. For example, you should make sure you're familiar with the [Remove-Erase idiom][1].
Now that you added some code I think I can see the problem :
int tid = _myVec.size();
You're using indice as ids.
Now, all depends on the way you delete your objects. (please show it for a more complete answer)
You just set the pointer to NULL.
You remove the pointer from the vector.
If you only do 1), then it should be safe (if you don't bother having a vector that grows and never get released and ids aren't re-used).
If you do 2. then this is all wrong : each time you remove an object from a vector, all the object still contains after the removed object position will be lowered by one. Making any stored id/index invalid.
Make sure you're coherent on this point, it is certainly a source of errors.
that segmentation fault is most probably and memory access violation. Some reasons
1) object already deallocated. be sure you set that array position on NULL after delete
2) you are out of array bounds
3) if you access that array from multiple threads make sure you are synchronizing correctly
If you're completely certain that pointer points to a valid object, and that the act of deleting it causes the crash, then you have heap corruption.
You should try using a ptr_vector, unlike your code, it's guaranteed to be exception-safe.
Hint: if you write delete, you're doing it wrong
You can't be sure that the object is still valid: the memory that was occupied by the object is not necessarily cleaned, and therefore, you can be seeing something that appears to be your object but it is not anymore.
You can use a mark in order to be sure that the object is still alive, and delete that mark in the destructor.
class A {
public:
static const unsigned int Inactive;
static const unsigned int Active;
A();
~A();
/* more things ...*/
private:
unsigned int mark;
};
const unsigned int A::Inactive = 0xDEADBEEF;
const unsigned int A::Active = 0x11BEBEEF;
A::A() : mark( Active )
{}
A::~A()
{
mark = Inactive;
}
This way, checking the first 4 bytes in your object you can easily verify whether your object has finished its live or not.