Calling delete on automatic objects - c++

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.

Related

Adding std::cout line eliminates memory corruption error

Here I have a class definition. It is a little long, but the focus will be on the move constructor and the destructor. Below the class definition is a short test.
#include <cassert>
#include <iostream>
#include <utility>
template <typename T>
class SharedPtr {
public:
SharedPtr() {}
explicit SharedPtr(T* input_pointer) : raw_ptr_(input_pointer), ref_count_(new size_t(1)) {}
SharedPtr(const SharedPtr& other) : raw_ptr_(other.raw_ptr_), ref_count_(other.ref_count_) {
if (ref_count_) {
++*ref_count_;
}
}
SharedPtr(SharedPtr&& other) : raw_ptr_(other.raw_ptr_), ref_count_(other.ref_count_) {}
SharedPtr& operator=(SharedPtr other) {
swap(other, *this);
return *this;
}
size_t use_count() const {
return ref_count_ ? *ref_count_ : 0;
}
~SharedPtr() {
if (ref_count_) {
--*ref_count_;
if (*ref_count_ == 0) {
delete raw_ptr_;
delete ref_count_;
}
}
}
private:
T* raw_ptr_ = nullptr;
size_t* ref_count_ = nullptr;
friend void swap(SharedPtr<T>& left, SharedPtr<T>& right) {
std::swap(left.raw_ptr_, right.raw_ptr_);
std::swap(left.ref_count_, right.ref_count_);
}
};
int main() {
// Pointer constructor
{
SharedPtr<int> p(new int(5));
SharedPtr<int> p_move(std::move(p));
assert(p_move.use_count() == 1);
}
std::cout << "All tests passed." << std::endl;
return 0;
}
If I run the code I get an error message indicating memory corruption:
*** Error in `./a.out': corrupted size vs. prev_size: 0x0000000001e3dc0f ***
======= Backtrace: =========
...
======= Memory map: ========
...
Aborted (core dumped)
We may suspect something is wrong with the move constructor: if we move from a SharedPtr and then later destruct that SharedPtr, it will still destruct as if it were an "active" SharedPtr. So we could fix that by setting the other object's pointers to nullptr in the move constructor.
But that's not the interesting thing about this code. The interesting thing is what happens if I don't do that, and instead simply add std::cout << "x" << std::endl; to the move constructor.
The new move constructor is given below, and the rest of the code is unchanged.
SharedPtr(SharedPtr&& other) : raw_ptr_(other.raw_ptr_), ref_count_(other.ref_count_) {
std::cout << "x" << std::endl;
}
The code now runs without error on my machine and yields the output:
x
All tests passed.
So my questions are:
Do you get the same results as I do?
Why does adding a seemingly innocuous std::cout line cause the program to run "successfully"?
Please note: I am not under any sort of impression that error message gone implies bug gone.
bolov's answer explains the cause of the undefined behavior (UB), when the move constructor of SharedPtr does not invalidate the moved-from pointer.
I disagree with bolov's view that it is pointless to understand UB. The question why code changes result in different behavior, when facing UB, is extremely interesting. Knowing what happens can help debugging, on one hand, and it can help intruders intrude the system, on the other.
The difference in the code in question comes from adding std::cout << something. In fact, the following change also makes the crash go away:
{
SharedPtr<int> p(new int(5));
SharedPtr<int> p_move(std::move(p));
assert(p_move.use_count() == 1);
std::cout << "hi\n"; // <-- added
}
The std::cout << allocates some internal buffer, which std::cout << uses. The allocation in cout happens only once, and the question is if this allocation happens before or after the double free. Without the additional std::cout, this allocation happens after the double free, when the heap is corrupted. When the heap is corrupted, the allocation in std::cout << triggers the crash. But when there is a std::cout << before the double-free, there is no allocation after the double-free.
Let's have few other experiments to validate this hypothesis:
Remove all std::cout << lines. All works fine.
Move two calls to new int(some number) right before the end:
int main() {
int *p2 = nullptr;
int *cnt = nullptr;
// Pointer constructor
{
SharedPtr<int> p(new int(5));
SharedPtr<int> p_move(std::move(p));
assert(p_move.use_count() == 1);
}
p2 = new int(100);
cnt = new int(1); // <--- crash
return 0;
}
This crashes, since the new is attempted on a corrupted heap.
(you can try it out here)
Now move the two new lines to slightly up, right before the closing } of the inner block. In this case, the new is performed before the heap is corrupted, so nothing triggers a crash. The delete simply puts the data in the free list, which is not corrupted. As long as the corrupted heap is not touched, then things will work fine. One can call new int, and get a pointer of one of the lately released pointers, and nothing bad will happen.
{
SharedPtr<int> p(new int(5));
SharedPtr<int> p_move(std::move(p));
assert(p_move.use_count() == 1);
p2 = new int(100);
cnt = new int(1);
}
delete p2;
delete cnt;
p2 = new int(100); // No crash. We are reusing one of the released blocks
cnt = new int(1);
(you can try it out here)
The interesting fact is that the corrupted heap can be undetected to much later in the code. The computer may run millions of unrelated lines of code, and suddenly crash on a completely unrelated new in a completely different part of the code. This is why sanitizers and the likes of valgrind are needed: debugging memory corruption can be practically impossible to debug otherwise.
Now, the really interesting question is "can this be exploited more than for denial of service?". Yes it can. It depends on the kind of object that is destroyed twice, and what it does in the destructor. It also depends on what happens between the first destruction of the pointer, and its second free. In this trivial example, nothing substantial seems to be possible.
SharedPtr(SharedPtr&& other) : raw_ptr_(other.raw_ptr_), ref_count_(other.ref_count_) {}
When you move the moved from object remains the same. This means that at some point in your program you will delete raw_ptr_ twice for the same memory. The same for ref_count_. This is Undefined Behavior.
The behaviour you observe falls well within Undefined Behavior because that's what UB means: the standard doesn't mandate absolutely any kind of behavior from your program. Trying to understand why exactly happens what happens on your particular compiler and your particular version on your particular platform with your specific flags is ... kind of pointless.

how to assert a pointer's pointed content is on heap? [duplicate]

Example:
bool isHeapPtr(void* ptr)
{
//...
}
int iStack = 35;
int *ptrStack = &iStack;
bool isHeapPointer1 = isHeapPtr(ptrStack); // Should be false
bool isHeapPointer2 = isHeapPtr(new int(5)); // Should be true
/* I know... it is a memory leak */
Why, I want to know this:
If I have in a class a member-pointer and I don't know if the pointing object is new-allocated. Then I should use such a utility to know if I have to delete the pointer.
But:
My design isn't made yet. So, I will program it that way I always have to delete it. I'm going to avoid rubbish programming
There is no way of doing this - and if you need to do it, there is something wrong with your design. There is a discussion of why you can't do this in More Effective C++.
In the general case, you're out of luck, I'm afraid - since pointers can have any value, there's no way to tell them apart. If you had knowledge of your stack start address and size (from your TCB in an embedded operating system, for example), you might be able to do it. Something like:
stackBase = myTCB->stackBase;
stackSize = myTCB->stackSize;
if ((ptrStack < stackBase) && (ptrStack > (stackBase - stackSize)))
isStackPointer1 = TRUE;
The only "good" solution I can think of is to overload operator new for that class and track it. Something like this (brain compiled code):
class T {
public:
void *operator new(size_t n) {
void *p = ::operator new(n);
heap_track().insert(p);
return p;
}
void operator delete(void* p) {
heap_track().erase(p);
::operator delete(p);
}
private:
// a function to avoid static initialization order fiasco
static std::set<void*>& heap_track() {
static std::set<void*> s_;
return s_;
}
public:
static bool is_heap(void *p) {
return heap_track().find(p) != heap_track().end();
}
};
Then you can do stuff like this:
T *x = new X;
if(T::is_heap(x)) {
delete x;
}
However, I would advise against a design which requires you to be able to ask if something was allocated on the heap.
Well, get out your assembler book, and compare your pointer's address to the stack-pointer:
int64_t x = 0;
asm("movq %%rsp, %0;" : "=r" (x) );
if ( myPtr < x ) {
...in heap...
}
Now x would contain the address to which you'll have to compare your pointer to. Note that it will not work for memory allocated in another thread, since it will have its own stack.
here it is, works for MSVC:
#define isheap(x, res) { \
void* vesp, *vebp; \
_asm {mov vesp, esp}; \
_asm {mov vebp, ebp}; \
res = !(x < vebp && x >= vesp); }
int si;
void func()
{
int i;
bool b1;
bool b2;
isheap(&i, b1);
isheap(&si, b2);
return;
}
it is a bit ugly, but works. Works only for local variables. If you pass stack pointer from calling function this macro will return true (means it is heap)
In mainstream operating systems, the stack grows from the top while the heap grows from the bottom. So you might heuristically check whether the address is beyond a large value, for some definition of "large." For example, the following works on my 64-bit Linux system:
#include <iostream>
bool isHeapPtr(const void* ptr) {
return reinterpret_cast<unsigned long long int>(ptr) < 0xffffffffull;
}
int main() {
int iStack = 35;
int *ptrStack = &iStack;
std::cout << isHeapPtr(ptrStack) << std::endl;
std::cout << isHeapPtr(new int(5)) << std::endl;
}
Note that is a crude heuristic that might be interesting to play with, but is not appropriate for production code.
First, why do you need to know this? What real problem are you trying to solve?
The only way I'm aware of to make this sort of determination would be to overload global operator new and operator delete. Then you can ask your memory manager if a pointer belongs to it (the heap) or not (stack or global data).
Even if you could determine whether a pointer was on one particular heap, or one particular stack, there can be multiple heaps and multiple stacks for one application.
Based on the reason for asking, it is extremely important for each container to have a strict policy on whether it "owns" pointers that it holds or not. After all, even if those pointers point to heap-allocated memory, some other piece of code might also have a copy of the same pointer. Each pointer should have one "owner" at a time, though ownership can be transferred. The owner is responsible for destructing.
On rare occasions, it is useful for a container to keep track of both owned and non-owned pointers - either using flags, or by storing them separately. Most of the time, though, it's simpler just to set a clear policy for any object that can hold pointers. For example, most smart pointers always own their container real pointers.
Of course smart pointers are significant here - if you want an ownership-tracking pointer, I'm sure you can find or write a smart pointer type to abstract that hassle away.
Despite loud claims to the contrary, it is clearly possible to do what you want, in a platform-dependent way. However just because something is possible, that does not automatically make it a good idea. A simple rule of stack==no delete, otherwise==delete is unlikely to work well.
A more common way is to say that if I allocated a buffer, then I have to delete it, If the program passes me a buffer, it is not my responsibility to delete it.
e.g.
class CSomething
{
public:
CSomething()
: m_pBuffer(new char[128])
, m_bDeleteBuffer(true)
{
}
CSomething(const char *pBuffer)
: m_pBuffer(pBuffer)
, m_bDeleteBuffer(false)
{
}
~CSomething()
{
if (m_bDeleteBuffer)
delete [] m_pBuffer;
}
private:
const char *m_pBuffer;
bool m_bDeleteBuffer;
};
You're trying to do it the hard way. Clarify your design so it's clear who "owns" data and let that code deal with its lifetime.
here is universal way to do it in windows using TIP:
bool isStack(void* x)
{
void* btn, *top;
_asm {
mov eax, FS:[0x08]
mov btn, eax
mov eax, FS:[0x04]
mov top, eax
}
return x < top && x > btn;
}
void func()
{
int i;
bool b1;
bool b2;
b1 = isStack(&i);
b2 = isStack(&si);
return;
}
The only way I know of doing this semi-reliably is if you can overload operator new for the type for which you need to do this. Unfortunately there are some major pitfalls there and I can't remember what they are.
I do know that one pitfall is that something can be on the heap without having been allocated directly. For example:
class A {
int data;
};
class B {
public:
A *giveMeAnA() { return &anA; }
int data;
A anA;
};
void foo()
{
B *b = new B;
A *a = b->giveMeAnA();
}
In the above code a in foo ends up with a pointer to an object on the heap that was not allocated with new. If your question is really "How do I know if I can call delete on this pointer." overloading operator new to do something tricky might help you answer that question. I still think that if you have to ask that question you've done something very wrong.
How could you not know if something is heap-allocated or not? You should design the software to have a single point of allocation.
Unless you're doing some truly exotic stuff in an embedded device or working deep in a custom kernel, I just don't see the need for it.
Look at this code (no error checking, for the sake of example):
class A
{
int *mysweetptr;
A()
{
mysweetptr = 0; //always 0 when unalloc'd
}
void doit()
{
if( ! mysweetptr)
{
mysweetptr = new int; //now has non-null value
}
}
void undoit()
{
if(mysweetptr)
{
delete mysweetptr;
mysweetptr = 0; //notice that we reset it to 0.
}
}
bool doihaveit()
{
if(mysweetptr)
return true;
else
return false;
}
~A()
{
undoit();
}
};
In particular, notice that I am using the null value to determine whether the pointer has been allocated or not, or if I need to delete it or not.
Your design should not rely on determining this information (as others have pointed out, it's not really possible). Instead, your class should explicitly define the ownership of pointers that it takes in its constructor or methods. If your class takes ownership of those pointers, then it is incorrect behavior to pass in a pointer to the stack or global, and you should delete it with the knowledge that incorrect client code may crash. If your class does not take ownership, it should not be deleting the pointer.

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.

Confused with delete keyword operation in 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.

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