Accessing an already destroyed object does not cause segfault [duplicate] - c++

This question already has answers here:
Can a local variable's memory be accessed outside its scope?
(20 answers)
C++ delete - It deletes my objects but I can still access the data?
(13 answers)
Closed 7 years ago.
Out of fun, I decided to see what gdb would say about this code, which is meant to attempt to use methods of an already destroyed object.
#include <iostream>
class ToDestroy
{
public:
ToDestroy() { }
~ToDestroy() {
std::cout << "Destroyed!" << std::endl;
}
void print() {
std::cout << "Hello!" << std::endl;
}
};
class Good
{
public:
Good() { }
~Good() { }
void setD(ToDestroy* p) {
mD = p;
}
void useD() {
mD->print();
}
private:
ToDestroy* mD;
};
int main() {
Good g;
{
ToDestroy d;
g.setD(&d);
}
g.useD();
return 0;
}
The output is (built with -O0 flag):
Destroyed!
Hello!
Allocating d in the heap and deleting it causes the same behaviour (i.e., no crash).
I assume the memory has not been overwritten and C++ is 'tricked' into using it normally. However, I am surprised about the fact that, when allocating on the heap and deleting, one can use memory not assigned to them.
Can someone provide any more insight about this? Does this mean that when trying to dereference a pointer, if that memory happens to have something 'coherent' for our context the execution would not cause a SEGFAULT despite the memory not having been assigned to us?

A segfault happens when you try to access an address that the OS forbids you to access. This can be because the mem behind the address is not allocated to you process, or because it does not exist or whatever. So you are now trying to access a piece of memory that is still allocated to your process, so no segfault.
Malloc (the one that manages your heap) works with certain buffers to limit the amount of syscalls. So there is uninitialized mem that you can access.

You pass an invalid this pointer to print but it is never dereferenced as print is not virtual nor is it accessing any member.

Related

Accessing pointers after deletion [duplicate]

This question already has answers here:
What happens to the pointer itself after delete? [duplicate]
(3 answers)
Closed 3 years ago.
I have a code snippet like below. I have created some Dynamic memory allocation for my Something class and then deleted them.
The code print wrong data which I expect but why ->show does not crash?
In what case/how ->show will cause crash?
Is it possible to overwrite the same memory location of i, ii, iii with some other object?
I am trying to understand why after delete which frees up the memory location to be written with something else still have information about ->show!
#include <iostream>
#include <vector>
class Something
{
public:
Something(int i) : i(i)
{
std::cout << "+" << i << std::endl;
}
~Something()
{
std::cout << "~" << i << std::endl;
}
void show()
{
std::cout << i << std::endl;
}
private:
int i;
};
int main()
{
std::vector<Something *> somethings;
Something *i = new Something(1);
Something *ii = new Something(2);
Something *iii = new Something(3);
somethings.push_back(i);
somethings.push_back(ii);
somethings.push_back(iii);
delete i;
delete ii;
delete iii;
std::vector<Something *>::iterator n;
for(n = somethings.begin(); n != somethings.end(); ++n)
{
(*n)->show(); // In what case this line would crash?
}
return 0;
}
The code print wrong data which I expect but why ->show does not crash?
Why do you simultaneously expect the data to be wrong, but also that it would crash?
The behaviour of indirecting through an invalid pointer is undefined. It is not reasonable to expect the data to be correct, nor to expect the data to be wrong, nor to expect that it should crash, nor to expect that it shouldn't crash - in particular.
In what case/how ->show will cause crash?
There is no situation where the C++ language specifies the program to crash. Crashing is a detail of the particular implementation of C++.
For example, a Linux system will typically force the process to crash due to "segmentation fault" if you attempt to write into a memory area that is marked read-only, or attempt to access an unmapped area of memory.
There is no direct way in standard C++ to create memory mappings: The language implementation takes care of mapping the memory for objects that you create.
Here is an example of a program that demonstrably crashes on a particular system:
int main() {
int* i = nullptr;
*i = 42;
}
But C++ does not guarantee that it crashes.
Is it possible to overwrite the same memory location of i, ii, iii with some other object?
The behaviour is undefined. Anything is possible as far as the language is concerned.
Remember, a pointer stores an integer memory address. On a call to delete, the dynamic memory will be deallocated but the pointer will still store the memory address. If we nulled the pointer, then program would crash.
See this question: What happens to the pointer itself after delete?

Testing raw pointers c++, but could not find leaks [duplicate]

This question already has answers here:
method on deleted instance of class still work?
(4 answers)
Closed 5 years ago.
I am playing a bit with raw pointers on c++, I know that nowadays it is good practices to use smart pointers, but as I am learning c++ on my own, I would like first understand raw pointers before moving to smart pointers.
To play around I have created a fakeClass, and playing in a Xcode console project c++:
/** fakeClass.hpp **/
#ifndef fakeClass_hpp
#define fakeClass_hpp
namespace RPO {
class fakeClass {
private:
int _id;
public:
fakeClass(int id);
~fakeClass();
void message();
}; // end class
} // end namespace
#endif
/** fakeClass.cpp **/
#include "fakeClass.hpp"
#include <iostream>
namespace RPO {
fakeClass::fakeClass(int id) {
_id = id;
std::cout << "Creating object: " << _id << std::endl;
}
fakeClass::~fakeClass() {
std::cout << "Destroying objet: " << _id << std::endl;
}
void fakeClass::message() {
std::cout << "Object: " << _id << std::endl;
}
}
/** main.cpp **/
int main(int argc, const char * argv[]) {
// Instantiate on the stack
RPO::fakeClass fClass(1);
fClass.message();
// Instantiate on the heap
RPO::fakeClass *fClassPointer = new RPO::fakeClass(2);
fClassPointer->message();
fClassPointer = new RPO::fakeClass(3); // Create new object #3, on non deleted pointer
fClassPointer->message();
delete fClassPointer; // Free memory of object #3, but still pointing to the memory address
fClassPointer = nullptr; // pointer is pointing to null right now
fClassPointer->message(); // throws an error
}
Output:
Creating object: 1
Object: 1
Creating object: 2
Object: 2
Creating object: 3
Object: 3
Destroying object: 3
Destroying object: 1
Edited:
Thanks to the revisors, I have been searching but could not find anything, but the question posted by tobi303 answers one of my questions (about why one method is still responding after free the memory), but as I said on the title the main question was about leaks.
As it can be seen, object #2 is never destroyed, so it is an obvious memory leak. I breakpointed after creating the object #3, and typed on Console "leaks pruebaC", following instructions from this question, but I get no leak report... why?
leaks Report Version: 2.0
Process 1292: 147 nodes malloced for 17 KB
**Process 1292: 0 leaks for 0 total leaked bytes.**
Also tried after de fClassPointer = nullptr; with the same result.
So, 2 questions, why the leak didn't showed up? and, do the memory used by an app is freed when the app is terminated? (even if it is a memory leak with no pointers)
Thank you.
PS: extra bonus, when I see examples with "char *myString", should I "delete myString" after?
That is my question, I suppose is because memory is freed, but not yet overwritten, and that is why I get the "Object: 2" message after deleting the object #2. Is that correct?
This is "correct" in the sense that most implementations will behave this way, but your situation qualifies as "undefined behavior", so there is no guarantee that this will work accross different compilers, compiler versions, or architectures.
when running on Terminal "leaks pruebaC", I get no leak report... why?
There is no leak detector added by default, because it adds unnecessary weight to the program (makes it slow to shut down). You have to add a leak detector explicitely by yourself (like linking to tcmalloc).
when I see examples with "char *myString", should I "delete myString" after?
Here's a rule of thumb for this: Every new needs to be matched with a delete, and vice-versa.

No need to delete dynamic data? [duplicate]

This question already has answers here:
Is there a reason to call delete in C++ when a program is exiting anyway?
(8 answers)
Closed 8 years ago.
I have the following code:
class A {
public:
virtual void f() {
cout << "1" << endl;
}
};
class B : public A {
public:
void f {
cout << "2" << endl;
}
};
int main() {
A* a = new B();
a->f();
return 0;
}
And my question is: why there is no need to to delete a before return of the main function?
According to my understanding this code will result in a memory leak, am I wrong?
[UPDATE]
I checked the following code using valgrind and it confused me even more. It says there is a memory leak.
There is indeed a memory leak. It lasts from the return of main to the exit of the program, which in this case is very, very short.
"According to my understanding this code will result in a memory leak, am I wrong?"
No you're right, there should be a delete. Though the memory leak usually doesn't matter, since the OS will reclaim all memory allocated from the process after return 0;.

Pointer of class local variable? [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Can a local variable's memory be accessed outside its scope?
Is there worrying thing to do a code such (getIDs() returns a pointer):
class Worker{
private:
int workerID;
int departID;
int supervisorID;
public:
Worker()
{
workerID=0;
departID=0;
supervisorID=0;
name="anonymous";
workerAddress="none";
}
void setIDs(int worker, int depart, int supervisor)
{
workerID=worker;
departID=depart;
supervisorID=supervisor;
}
int* getIDs()
{
int id[3];
id[0]=workerID;
id[1]=departID;
id[2]=supervisorID;
return id;
}
};
And then, use it such:
Worker obj;
obj.setIDs(11,22,33);
cout<<(*obj.getIDs())<<endl;
cout<<++(*obj.getIDs())<<endl;
cout<<++(++(*obj.getIDs()))<<endl;
I am wondering about that because the compiler shows:
Warning 1 warning C4172: returning address of local variable or
temporary
Your int id[3] is allocated on a stack and gets destroyed when your int* getIDs() returns.
You're return a pointer to a variable that gets destroyed immediately after getIDs() returns. The pointer then becomes dangling and is practically useless as doing anyting with it is undefined behaviour.
Suppose you defined your class like this:
class Worker{
private:
int IDs[3];
public
// ...
int* getIDs() { return IDs; }
};
This partially solves your problem, as the pointer remains valid as long the Worker object is in scope, but it's still bad practice. Example:
int* ptr;
while (true) {
Worker obj;
obj.setIDs(11,22,33);
ptr = obj.getIDs();
cout << *ptr; // ok, obj is still alive.
break;
} // obj gets destroyed here
cout << *ptr; // NOT ok, dereferencing a dangling pointer
A better way of solving this is to implement your custom operator << for your class. Something like this:
class Worker {
private:
int workerID;
int departID;
int supervisorID;
public:
// ...
friend ostream& operator<<(ostream& out, Worker w);
};
ostream& operator<<(ostream& out, const Worker& w)
{
out << w.workerID << "\n" << w.departID << "\n" << w.supervisorID;
return out;
}
Even if this would work, it wouldn't be good practice to do it this way in c++ unless there is some profound reason why you want pointers to int. Raw c-syle arrays are more difficult to handle than, for instance, std::vectors, so use those, like
std::vector<int> getIDs(){
std::vector<int> id(3);
id[0]=workerID; id[1]=departID; id[2]=supervisorID;
return id;
}
If you're worried about the overhead: this is likely to be optimized away completely by modern compilers.
A local (also caled automatic) variable is destroyed once you leave the function where it is defined. So your pointer will point to this destroyed location, and of course referencing such a location outside the function is incorect and will cause undefined behaviour.
The basic problem here is that when you enter a function call, you get a new frame on your stack (where all your local variables will be kept). Anything that is not dynamically allocated (using new/malloc) in your function will exist in that stack frame, and it gets destroyed when your function returns.
Your function returns a pointer to the start of your 3-element-array which you declared in that stack frame that will go away. So, this is undefined behavior.
While you may get "lucky/unlucky" and still have your data around where the pointer points when you use it, you may also have the opposite happen with this code. Since the space is given up when the stack frame is destroyed, it can be reused - so another part of your code could likely use the memory location where your three elements in that array is stored, which would mean they would have completely different values by the time you dereferenced that pointer.
If you're lucky, your program would just seg-fault/crash so you knew you made a mistake.
Redesign your function to return a structure of 3 ints, a vector, or at the very least (and I don't recommend this), dynamically allocate the array contents with new so it persists after the function call (but you better delete it later or the gremlins will come and get you...).
Edit: My apologies, I completely misread the question. Shouldn't be answering StackOverflow before my coffee.
When you want to return an array, or a pointer rather, there are two routes.
One route: new
int* n = new int[3];
n[0] = 0;
// etc..
return n;
Since n is now a heap object, it is up to YOU to delete it later, if you don't delete it, eventually it will cause memory leaks.
Now, route two is a somewhat easier method I find, but it's kind of riskier. It is where you pass an array in and copy the values in.
void copyIDs(int arr[3] /* or int* arr */)
{
arr[0] = workerID;
/* etc */
}
Now your array is populated, and there was no heap allocation, so no problem.
Edit: Returning a local variable as an address is bad. Why?
Given the function:
int* foo() {
int x = 5;
return &x; // Returns the address (in memory) of x
} // At this point, however, x is popped off the stack, so its address is undefined
// (Garbage)
// So here's our code calling it
int *x = foo(); // points to the garbage memory, might still contain the values we need
// But what if I go ahead and do this?
int bar[100]; // Pushed onto the stack
bool flag = true; // Pushed onto the stack
std::cout << *x << '\n'; // Is this guaranteed to be the value we expect?
Overall, it is too risky. Don't do it.

Program Crashes on NULL Pointer object

I am trying a code which Goes like this:-
class test{
int test_int;
public:
virtual int show()
{
return test_int;
}
void set_int(int data){
std::cout<<"received data "<< data <<endl;
test_int = data;
}
};
int main()
{
test *ptr=new test();
ptr=NULL;
ptr->set_int(5);
return 0;
}
Now the problem i am facing is my program after printing the data which i am sending through set_int function got printed but the program crashes just after the completition of the function(set_int).
Am i doing any mistake that is not according to the language standards?
TIA.
Am i doing any mistake that is not according to the language standards?
Yes, you are.
You may not call member functions on a pointer that does not point to a valid object of that type. A null pointer never points to a valid object.
The trivial fix here is to remove the line ptr=NULL;. That way ptr still points to an object when the member function is invoked. This also allows you to fix the memory leak by deleting the pointer later. As a sidenote: avoid manual memory management.
You have pointer to test (test*) set to dynamicaly allocated memory representing instance of that class.
Right after that, you wrote "Nah, I do not need it anymore" and you forget where that newly allocated memory was.
Finally, you are trying to access an object on address 0, which is an invalid operation and will cause runtime error.
You probably meant to do this
int main()
{
test *ptr = new test();
ptr->set_int(5);
// ptr = NULL; // wont free the memory allocated by new
delete ptr; // memory deallocation
ptr = NULL; // now we can safely forget that address (which is now invalid anyways)
return 0;
}