Confused with delete keyword operation in C++ - c++

I would like to know how delete works?
In main function I have deleted the cfact object. But still the cfact->Hello() works instead of throwing an error.
While debugging I found while delete happens, cfact releases the memory. as soon as factory* c2fact = newfun.Newfun("c2_fact"); line executes cfact gets some memory location.
class factory{
public:
virtual void Hello() = 0;
};
class c_fact: public factory
{
public:
void Hello(){
cout << "class c_fact: public factory"<<endl;
}
};
class c2_fact: public factory
{
public:
void Hello(){
cout << "class c2_fact: public factory"<<endl;
}
};
class callFun{
public:
virtual factory* Newfun(string data)
{
if(data == "c_fact")
{return new c_fact;}
else
{return new c2_fact;}
}
};
class newFun:public callFun{
public:
factory* Newfun(string data)
{
if(data == "c_fact")
{return new c_fact;}
else if (data == "c2_fact")
{return new c2_fact;}
}
};
int main()
{
newFun newfun;
factory* cfact = newfun.Newfun("c_fact");
delete cfact; //Deleted the instance
factory* c2fact = newfun.Newfun("c2_fact");
cfact->Hello();//Still it prints the output
c2fact->Hello();
system("pause");
return 0;
}

delete doesn't actually invalidate what it points to. It just tells the OS that the memory can be used for something else and that the program doesn't need it anymore.
If it not overwritten by other data your data will still be in memory and will still be accessible. This is a cause of many bugs that go undetected during development phase and later show up.
The fact that is is working now doesn't mean it will always work. For example if you move the code to another machine or if you restart your computer the code might segfault.
It is always a good practice to set pointers to NULL after delete. Or even better use smart pointers.

This is undefined behavior, most likely this works because the method Hello is not using any of the classes variables and thus is not using the this pointer. Trying outputting this in Hello and you should see an invalid pointer after the call to delete:
std::cout << std::hex << this << << std::endl ;
In my test case it comes back as 0 after delete

Dereferencing a deleted pointer is undefined behaviour. That means anything can happen, including the program appearing to "work". You cannot rely on any such behaviour.

When you delete the memory it is released. however, the content is usually not changed, so anything that is written in that memory is still there after the delete, but you don't know how long it will stay, as other functions can grab it and overwrite it with their own data.
On some compilers, when compiling in debug mode, the memory is marked, so that you can detect such errors as you did by reusing the deleted pointer. However that is not necessarily the default. So you should never reuse a pointer that was deleted.

Sorry I can't comment...
I compiled your code and you can observe that c2fact replaces the cfact you just destroyed (the output is
class c2_fact: public factory
class c2_fact: public factory
)
BTW if you put "cfact->Hello();" before you create your c2fact, the program may crash (which is what you seem to wish) because the mem blocks are not affected to any object. Note that this behavior may change depending on the memory monitoring and other running processes.

Related

C++ Member function able to access data even it deleted the object that called it

Here is a scenario I came across :-
#include <iostream>
class Agent;
class State;
class OffState;
class OnState;
class State
{
public:
virtual void execute(Agent * agent) = 0;
virtual ~State() {std::cout << "removing State\n";}
};
class Agent{
State * currentState ;
public:
Agent();
void update(){
std::cout << "agent updating. will execute current State " << std::endl;
currentState->execute(this);
}
void changeState(State * newState){
delete currentState;
currentState = newState;
}
};
class OffState : public State
{
public:
~OffState() {std::cout << "deleting OffState Object" <<std::endl;}
void execute(Agent * agent){
std::cout << "Nothing happens in the off State " << std::endl;
}
};
class OnState : public State
{
static int count ;
int id;
public:
OnState(){
id = count;
count++;
}
~OnState() {std::cout << "removing OnState id :- " <id<<std::endl;}
void execute(Agent * agent){
std::cout << "OnState executing" << std::endl;
agent->changeState(new OffState());
std::cout << "executed after deleting OnState ? id:- " << id << std::endl;
}
};
int OnState::count = 0;
Agent::Agent():currentState(new OnState()){
}
main(){
Agent smith;
smith.update();
}
In this, the Agent's current state is initialised to an OnState object. This object is accessed via the update() method in Agent. This calls the OnState's execute method. Now this execute method indirectly deletes the OnState object which called it. Yet after that, control is passed back to the execute() method in the OnState object. What's more it is able to print the value of "id" . Shouldn't the memory pointed be deleted because of the delete currentState .
Or is this the case where in some cases, the system may crash and in some cases, the memory contents wouldn't be immediately filled up by the operating system.
I thought that the function definition isn't stored in memory specific to instances as such, but this does not explain how the "id" value is still accessible.
The output of the code was :-
agent updating. will execute current State
OnState executing
removing OnState id :- 0
removing State
executed after deleting OnState ? id:- 0
Regards.
You can only delete pointers, not references.
Check this link . This might help you.
Question 1 "why still can access deleted instance's virtual functions and member variable"
Function call use instance when calling virtual functions and member variables, in following scenario: After your deletion, if another allocation incidentally allocated in your released block, and change the virtual function pointer's values in your deleted instance, which would trigger exception when you called.
Memory deletion only result in heap block returned back to free list of heap by heap management.(both for glibc and windows heap). Heap never return virtual pages back to virtual memeory manager, which means deleted memory in heap you can access and when only read in valid range wouldn't trigger any exception.
Question 2 "I thought that the function definition isn't stored in memory specific to instances as such, but this does not explain how the "id" value is still accessible."
Function definition in your executable file is in code segment(for dll would shared between processes and in some senrior would trigger COW), Newed variables are allocated in heap. As explained, memory can be accessed, so before the heap block is taken by other allocation, you still can access your previous value(As i know both windows heap and glic wouldn't refill or reset the deletion block's value because of performance).
Accessing a member of a deleted object results in undefined behavior.
Reading a deleted object's member value will usually return whatever is present at that address. Bear in mind that a new object can be allocated at that address in the meantime, so you can get a different value from the old member value.
You're using the new operator to allocate the OnState object, so it will be allocated on the heap. A member variable is part of the object stored in heap memory and you have a pointer to it. Even if you deleted the object, you can still read its members through the pointer.
The read access should never throw an exception as long as virtual memory pages are not reclaimed (anyway, it's a bad idea to rely on this assumption).

Using malloc/free to simulate new/delete

I created an example classes (only for learning purposes) which don't have to use constructor initialization lists because I want to get the same effects using new/delete and malloc/free. What are other constraints besides not using constructor initialization list? Do you think that the following code simulate the new/delete behavior in the right way?
#include <iostream>
using namespace std;
class X
{
private:
int* a;
public:
X(int x)
{
this->a = new int;
*(this->a) = x;
}
~X() { delete this->a; }
int getA() { return *(this->a); }
};
class Y
{
private:
int* a;
public:
void CTor(int x)
{
this->a = new int;
*(this->a) = x;
}
void DTor() { delete this->a; }
int getA(){ return *(this->a); }
};
void main()
{
X *xP = new X(44);
cout<<xP->getA()<<endl;
delete xP;
Y *yP = static_cast<Y*>(malloc(sizeof(Y)));
yP->CTor(44);
cout<<yP->getA()<<endl;
yP->DTor();
free(yP);
system("pause");
}
Without using delete xP, destructor will be called automatically when program ends, but a free store won't be freed (i.e. free store for xP, free store for field a will be freed) . When using delete xP destructor is called and then a free store is completely freed.
Please correct me if I'm wrong.
The actual answer to your question is that you are incorrect, not calling delete xP will lead to a memory leak. It is very likely that the OS then cleans up the memory for you, but it's not GUARANTEED by the C++ runtime library that this happens - it's something that OS's generally offer as a nice service [and very handy it is too, since it allows us to write imperfect code and have code that does things like if (condition) { cout << "Oh horror, condition is true, I can't continue" << endl; exit(2); } without having to worry about cleaning everything up when we've got something that went horribly wrong].
My main point, however, is that this sort of stuff gets very messy as soon as you add members that in themselves need destruction, e.g.
class X
{
private:
std::string str;
...
};
There is no trivial way to call the destructor for str. And it gets even worse if you decide to use exceptions and automated cleanup.
There are many subtle differences that distinguish new from malloc and delete from free. I believe they are only equivalent if the class is POD type.
I should warn that you can never mix the two types freely. A new must always be balanced by a delete and never by a free. Similarly malloc must be balanced only by free. Mixing the two results in undefined behaviour.

Calling delete on automatic objects

Consider the following c++ code:
class test
{
public:
int val;
test():val(0){}
~test()
{
cout << "Destructor called\n";
}
};
int main()
{
test obj;
test *ptr = &obj;
delete ptr;
cout << obj.val << endl;
return 0;
}
I know delete should be called only on dynamically allocated objects but what would happen to obj now ?
Ok I get that we are not supposed to do such a thing, now if i am writing the following implementation of a smart pointer, how can i make sure that such a thing does't happen.
class smart_ptr
{
public:
int *ref;
int *cnt;
smart_ptr(int *ptr)
{
ref = ptr;
cnt = new int(1);
}
smart_ptr& operator=(smart_ptr &smptr)
{
if(this != &smptr)
{
// House keeping
(*cnt)--;
if(*cnt == 0)
{
delete ref;
delete cnt;
ref = 0;
cnt = 0;
}
// Now update
ref = smptr.ref;
cnt = smptr.cnt;
(*cnt)++;
}
return *this;
}
~smart_ptr()
{
(*cnt)--;
if(*cnt == 0)
{
delete ref;
delete cnt;
ref = 0;
cnt = 0;
}
}
};
You've asked two distinct questions in your post. I'll answer them separately.
but what would happen to obj now ?
The behavior of your program is undefined. The C++ standard makes no comment on what happens to obj now. In fact, the standard makes no comment what your program does before the error, either. It simply is not defined.
Perhaps your compiler vendor makes a commitment to what happens, perhaps you can examine the assembly and predict what will happen, but C++, per se, does not define what happens.
Practially speaking1, you will likely get a warning message from your standard library, or you will get a seg fault, or both.
1: Assuming that you are running in either Windows or a UNIX-like system with an MMU. Other rules apply to other compilers and OSes.
how can i make sure that [deleteing a stack variable] doesn't happen.
Never initialize smart_ptr with the address of a stack variable. One way to do that is to document the interface to smart_ptr. Another way is to redefine the interface so that the user never passes a pointer to smart_ptr; make smart_ptr responsible for invoking new.
Your code has undefined behaviour because you used delete on a pointer that was not allocated with new. This means anything could happen and it's impossible to say what would happen to obj.
I would guess that on most platforms your code would crash.
Delete's trying to get access to obj space in memory, but opperation system don't allow to do this and throws (core dumped) exception.
It's undefined what will happen so you can't say much. The best you can do is speculate for particular implementations/compilers.
It's not just undefined behavior, like stated in other answers. This will almost certainly crash.
The first issue is with attempting to free a stack variable.
The second issue will occur upon program termination, when test destructor will be called for obj.

Deletion of this pointer

This is regarding deletion of this pointer for an object allocated on heap.Program is as follows,
class Sample{
private:
int m_value1;
int m_value2;
public:
Sample();
void setValues(int m_value1, int m_value2);
void display();
};
Sample::Sample(){
this->m_value1 = 0;
this->m_value2 = 0;
}
void Sample::setValues(int m_value1, int m_value2){
this->m_value1= m_value1;
this->m_value2 = m_value2;
display();
if(this != NULL)
{
cout <<"Deleting this pointer!"<<endl;
delete this;
cout <<"this->m_value1 is "<<this->m_value1<<endl;
cout <<"this->m_value2 is "<<this->m_value2<<endl;
}
}
void Sample::display(){
cout <<"Values are "<<this->m_value1<<" and "<<this->m_value2<<endl;
}
int main(){
Sample *obj1 = new Sample();;
obj1->setValues(4,6);
obj1->display();
getch();
}
OUTPUT:
Values are 4 and 6
Deleting this pointer!
this->m_value1 is 65535
this->m_value2 is 6
Values are 65535 and 6
Why does the value for m_value1 disappear whereas it stays for the other variable m_value2?
Accessing member variables after delete this is undefined behavior - anything can happen, including unexpected data being read, program crashing or anything else. The object has been destroyed and deallocated and you try to dereference an invalid pointer. Once delete this has happened - don't try to access the member variables, don't try t call member functions and don't do anything else (including comparing or casting) to this pointer.
Why does the value for m_value1 disappear whereas it stays for the other variable m_value2?
You are accessing memory after you deleted it. That means you are invoking undefined behavior.
So anything might happen, and your observation is as right or wrong as anything else.
What's likely going on is that the part of memory where m_value1 was stored is reused for something else, whilst the storage for m_value2 has not been used for something else (yet).
It's a matter of chance, probably the operator<< or whatever your do after deleting this allocates enough memory to overwrite the one and not the other.
But when you do something that shouldn't be done you should not rely on any particular consequences.
Dangerous and unpredictable outputs expected including system crash!
Do not delete location pointed to by this directly. its not a good programming practice. and don't use memory after deleting. and even if u have to put it inside an assert()
this != NULL // this will never be NULL if used properly.

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;
}