I am having a hard time getting used to the way C++ handles dynamic and automatic memeory. My question:
Can a pointer, that points to an automatic allocated instance, keep that instance from deallocation even after the scope of the instanciation has been left?
In this post I read that all pointers pointing to dealloc memory are invalid. But is this guy talking about the behaviour after a manual dealloc or an automatic dealloc?
This is an example:
int main(){
UiTreeRecord child = UiTreeRecord::UiTreeRecord();
createSomeScope(child);
//Does child still have a valid parent?
//Or does parent point to a piece of memory that has been deallocated?
}
void createSomeScope(const UiTreeRecord& child){
UiTreeRecord root = UiTreeRecord::UiTreeRecord();
child.attachParent(root);
}
void UiTreeRecord::attachParent(UiTreeRecord& newParent) {
if(parent != nullptr) {
detachParent();
}
parent = &newParent;
}
automatic memory: When is it deallocated?
When the variable goes out of scope. Or in the case of automatic member variable, when the owning object is destroyed.
Can a pointer, that points to an automatic allocated instance, keep that instance from deallocation even after the scope of the instanciation has been left?
No, it can't. The pointer simply keeps pointing at the memory that is now invalid. Pointers and references to a destroyed object always become invalid regardless of the way the object was destroyed - be it automatic, dynamic or static deallocation.
In your example, root is deallocated at the end of createSomeScope and the pointer that you assigned in UiTreeRecord::attachParent becomes invalid.
It is potentially dangerous to do stuff like this. Either use * or use &, but don't use the pointer of a reference as the reference might get invalidated like in your case. In your example you create an instance first, then pass it as reference to attachParent(), then convert it to a pointer but the instance will be deallocated when createSomeScope() returns, thus your pointer becomes invalid.
void createSomeScope(const UiTreeRecord& child){
UiTreeRecord root = UiTreeRecord::UiTreeRecord();
child.attachParent(root);
}
root is invalid immediately after the function is ends and controlling the deallocation is not possible afaik. Memory might be freed at different "times" depending on code optimizations etc.
Related
I know this is pretty common question, but still new for me!
I don't understand concept of dangling pointer, was googling around, and writing test methods to find one.
I just wonder is this a dangling pointer? As whatever example I found was returning something, here I'm trying something similar!
Thanks!
void foo(const std::string name)
{
// will it be Dangling pointer?!, with comments/Answer
// it could be if in new_foo, I store name into Global.
// Why?! And what is safe then?
new_foo(name.c_str());
}
void new_foo(const char* name)
{
// print name or do something with name...
}
A dangling pointer is a pointer that points to invalid data or to data which is not valid anymore, for example:
Class *object = new Class();
Class *object2 = object;
delete object;
object = nullptr;
// now object2 points to something which is not valid anymore
This can occur even in stack allocated objects:
Object *method() {
Object object;
return &object;
}
Object *object2 = method();
// object2 points to an object which has been removed from stack after exiting the function
The pointer returned by c_str may become invalid if the string is modified afterwards or destroyed. In your example you don't seem to modify it, but since it's not clear what you are going to do with const char *name it's impossible to know it your code is inherently safe or not.
For example, if you store the pointer somewhere and then the corresponding string is destroyed, the pointer becomes invalid. If you use const char *name just in the scope of new_foo (for example, for printing purposes) then the pointer will remain valid.
A dangling pointer is a (non-NULL) pointer which points to unallocated (already freed) memory area.
The above example should be correct given that the string is not modified through new_foo.
Taken from here. Although, even if this is for C, it is the same for C++.
Dangling Pointer
When a pointer is pointing at the memory address of a variable but after some time that variable is deleted from that memory location while the pointer is still pointing to it, then such a pointer is known as a dangling pointer and this problem is known as the dangling pointer problem.
Initially
Later
Example
#include<stdio.h>
int *call();
int main() {
int *ptr;
ptr = call();
fflush(stdin);
printf("%d", *ptr);
return 0;
}
int * call() {
int x=25;
++x;
return &x;
}
Its output will be garbage because the variable x is a local variable. Its scope and lifetime are within the function call hence after returning the address of x variable x becomes dead and the pointer is still pointing to that location.
As a matter of style, I explain a dangling pointer as "a pointer which still exists, even though the object it pointed to no longer exists".
In your case, the pointer name exists for a shorter period that the object that it points to. So it's never dangling.
Inside common C++ classes, pointers dangle for a very short period, inside destructors. That's because the delete statement is before the last } of the destructor, while the pointer itself ceases to exist at the last }. If you don't want to worry about this, use e.g. unique_ptr<T>. The T* pointer will dangle for a very short time inside the unique_ptr::~unique_ptr destructor, which is perfectly safe.
Dangling pointers is a situation where you have valid pointers in the stack, but it is pointing to invalid memory. You might end up in this situation when you deallocate the heap memory before the pointers in stack deallocated.
This is a security issue. Because when you deallocate a memory, we are informing Operating System, that we no longer need this section of memory. So OS will mark that piece of memory as ready to allocate and allocate to other applications when they request for memory.
Usually, in C++, memory allocated and deallocated through a general pattern. Constructor in a class gets invoked when a class initialised and this is the right place to allocate memory in heap.Destructor will be invoked when the class instance goes out of scope, and this is the right place to deallocate memory from heap. Assume we already created a class that does allocation and deallocation of memory in constructor and destructor respectively.
int main() {
SomeClass pointer1 = SomeClass();
SomeClass pointer2 = pointer1;
}
In the above example code, there are two variables declared but both holding the same value. When the constructor invoked, it allocates a heap memory. Then we are declaring one more variable and assigning the same value. In C++ usually, when you assign a value of complex type, it does a shallow copy (unless you explicitly implemented copy constructor) instead of deep copy. That means the only pointer gets copied in Stack, but not the heap memory. Actually it is not recommended to copy heap memory for performance reasons. Now the final memory layout looks like that we have two pointers pointing to the same heap memory.
Now when the function is done with execution, local variables goes out of scope and it invokes destructor. First, pointer2 invokes destructor that deallocates the heap memory. At this point, pointer1 becomes dangling pointer. It points to a memory that is already deallocated.
From this example, we understood that the primary cause of dangling pointer is having multiple owners for the same resource. Because when one pointer deallocates memory other pointers became dangling pointers.
//Declaring two pointer variables to int
int * ptr1;
int * ptr2;
// Allocating dynamic memory in the heap
ptr1 = new int;
ptr2 = ptr1; // Having both pointers to point same dynamic memory location
//deleting the dynamic memory location
delete ptr1;
ptr1 = nullptr;
//ptr2 is still pointing the already deleted memory location
//We call ptr2 is a dangling pointer
Dangling Pointer and dangling pointer problem
If any pointer is pointing the memory address of any variable but after some variable has deleted from that memory location while pointer is still pointing such memory location.
That pointer is called as dangling pointer and the problem that arises at that time is called as dangling pointer problem.
Here are some examples: Dangling Pointer and dangling pointer problem
In the code below, drvdCls derives from bseCls. This code compiles and runs as it is. I however find an issue here: newBse will get deallocated after Test() exits. Am I right?
bseCls* Test()
{
bseCls* newBse = new drvdCls();
drvdCls newDrvd;
newBse = &newDrvd;
return newBse;
}
The object originally pointed to by newBse will be leaked. When you assigned the address of newDrvd to newBse you are losing the pointer to the heap-allocated object, and you will not be able to delete it. This memory will be unusable until the process terminates.
Additionally, you are returning the address of a stack-allocated object as a pointer, which is bad for two reasons:
The object's destructor will have been called before the function returns, meaning you would be using a pointer to a destructed object.
The memory allocated for the object lives on the stack and will almost certainly be clobbered by future function calls. At that point, your pointer will be point at something that is not a bseCls, but you will be using it as though it were.
If you use the pointer returned by this function, you are invoking undefined behavior and your program has license to do anything.
No, it won't be automatically deallocated. Every call to new must be matched by a call to delete. But that's not the only problem with your code, you're also returning the address of a local variable from the function.
newBse = &newDrvd; // memory leak, pointer to previously allocated object is lost
return newBse; // newDrvd is destroyed when function exits, so returned
// pointer points to invalid memory
What you probably want to do is
bseCls* Test()
{
return new drvdCls();
}
Now the caller must call delete on the returned pointer after using it. What you should do is
std::unique_ptr<bseCls> Test()
{
return new drvdCls();
}
Now the allocated object will automatically be deleted when the returned unique_ptr goes out of scope.
Hi i have few doubt related to heap variable...
I want to write a function as below ->
struct test
{
int x;
int y;
};
test* fun()
{
test *ptr = new test;
return ptr;
}
My doubt is returning a heap variable once it will go out of scope it will lost its value.
There is definitely a memory leak.(As heap variable is not deleted.)
So how can i design such kind of function.
Dynamically allocated objects (what you call heap variables) do not get destroyed at the end of the scope in which they were created. That's the whole point of dynamic allocation. While the test object is dynamically allocated, the pointer ptr is not - it will be destroyed when it goes out of scope. But that's okay! You copy the value of the pointer out of the function and this copy still points at the test object. The test object is still there. The function you've written is fine, but it isn't exactly good style.
Yes, there is a memory leak if nobody ever does delete on a pointer to the test object you created. That's a problem with returning raw pointers like this. You have to trust the caller to delete the object you're creating:
void caller()
{
test* p = fun();
// Caller must remember to do this:
delete p;
}
A common C-style way of doing this (which is definitely not recommended in C++) is to have a create_test and destroy_test pair of functions. This still puts the same responsibility on the caller:
void caller()
{
test* p = create_test();
// Caller must remember to do this:
destroy_test(p);
}
The best way to get around this is to not use dynamic allocation. Just create a test object on the stack and copy it (or move it) out of the function:
test fun()
{
test t;
return t;
}
If you need dynamic allocation, then you should use a smart pointer. Specifically, the unique_ptr type is what you want here:
std::unique_ptr<test> fun()
{
return std::unique_ptr<test>(new test());
}
The calling function can then handle the unique_ptr without having to worry about doing delete on it. When the unique_ptr goes out of scope, it will automatically delete the test object you created. The caller can however pass it elsewhere if it wants some other function to have the object.
You are not returning a heap variable, you are returning a value of a stack variable that holds a pointer to the heap. The stack variable goes out of scope; the memory pointed to by the pointer is in the heap - it never goes out of scope.
There will be a memory leak unless you release the memory in the caller.
My doubt is [that] returning a heap variable once it will go out of scope it will lo[se] its value.
No worry, because since you're returing the pointer by value; so the pointer will go out of scope, but since you're returning the memory that it points to, there is no memory leak (only if we can rely on the caller to delete it).
However, if we had returned the pointer by reference then we would have a problem:
test*& fun() // note the & (reference)
{
test *ptr = new test;
return ptr;
}
Here you're returning a reference to a temporary. When the variable goes out of scope you will be using an object that doesn't exist. This is why you can't return temporaries by reference.
My doubt is returning a heap variable once it will go out of scope it will lost its value.
No heap variable does not go out of scope as do go stack variables...
There is definitely a memory leak.(As heap variable is not deleted.)
Yes we have to free memory allocated on heap by ourself, otherwise there is memory leak...
I would suggest to read some tutorial related to it.
I know from reading parashift.com that using delete on a pointer frees the memory
[16.1] Does delete p delete the pointer p, or the pointed-to-data *p?
The pointed-to-data.
The keyword should really be delete_the_thing_pointed_to_by. The same
abuse of English occurs when freeing the memory pointed to by a
pointer in C: free(p) really means free_the_stuff_pointed_to_by(p).
And the wiki article on "delete (C++)" says "many programmers set the pointer to NULL afterwards to minimize programming errors"
Is it necessary to think about deleting the pointer itself?
Is it correct to say that a declared pointer still takes up memory?
i.e. if I were to declare billions of different pointers to NULL, it would still use up memory (and hence I would have a need to delete the pointer itself).
How would I delete the pointer?
Usually the pointer will stop existing at the end of the scope.
Example:
{
int *p = NULL;
// do something with p
} // <-- p will be destroyed here
Hereby the pointer variable is said to have automatic storage duration. If done consistently, assigning 0, or NULL, or nullptr to a pointer variable that doesn't point to an object of the specified type has the advantage that one can easily recognize whether or not it's safe to dereference the pointer. This practice has no direct connection to the lifetime of the pointer or the previously pointed to object (if any).
In contrast, when you have the following code:
{
int *p = new int;
// do something with p
//delete p; // <-- the object p points to will not be destroyed unless it's deleted
} // <-- p will be destroyed here
Again, the pointer variable itself will be destroyed at the end of the scope, because it has automatic storage duration.
In contrast, the int object, which we have allocated using the new operator, to which the pointer points in this example, has dynamic storage duration. It will continue to reside in memory until delete is called to free it. This may result in a memory leak (if you lose any reference to the object p pointed to, as in this example).
Of course, if the pointer is dynamically created by itself, e.g., as in
{
int** p = new int*;
// do something with p
//delete p; // <-- the object p points to will not be destroyed unless it's deleted
} // <-- p will be destroyed here
... this could be the starting point for a recursive example.
Note that there is a thing called static storage duration, which means the variable will exist until the end of the program (e.g., global or static variables). If you want to read up more on this topic see:
http://en.cppreference.com/w/cpp/language/storage_duration
http://en.cppreference.com/w/cpp/language/static
Note that independent of its storage duration, any variable (including pointers) takes up some amount of memory. Generally, if you allocate space for too many objects at the same time you will run out of memory. Therefore, you should avoid implementing things like infinite recursion, fork bombs, memory leaks, or alike.
Is it necessary to think about deleting the pointer itself?
It is only necessary if the pointer itself has no automatic memory management. That is, if storage for the pointer itself was allocated with new or malloc.
Is it correct to say that a declared pointer still takes up memory?
A pointer takes up memory, it has to be stored somewhere in order to be used, right?
if I were to declare billions of different pointers to NULL, it would still use up memory (and hence I would have a need to delete the pointer itself).
Of course it would use up memory, billions * sizeof(void*). Needing to delete the pointer has nothing to do with it taking space or not, everything takes space (well, almost, there are some special optimizations); you only need to delete what was allocated with new.
How would I delete the pointer?
How was it allocated? If it has automatic storage then its memory will be automatically freed when the pointer goes out of scope. If it was allocated with new it has to be deleted with delete, same for new[]/delete[] and malloc/free.
1) Usually a pointer is on the stack or a member of another class and you wouldn't need to worry about deleting such pointer.
2) Yes.
3) Yes, they would use up memory and you would need to release the pointer.
4) Either let a local pointer fall out of scope, or get rid of whichever object contains it.
Finally note that raw pointers are quite out of favor. Prefer either an appropriate container such as vector, or as needed an appropriate smart pointer.
A declared pointer takes up memory on the stack and will be deleted when it goes out of scope. This is the same process that takes place with primitive types. You do not need to worry about memory management for anything on the stack.
The new operator on the other hand allocates memory on the heap, and must be explicitly deleted with delete.
Is it necessary to think about deleting the pointer itself?
it depends on how the pointer was created. if you create a pointer on the stack:
void func(void) {
int* p;
...
}
you should delete the memory pointed to by p (when it makes sense), but p is simply an auto variable which will be "deleted" when the stack is unwind;
Is it correct to say that a declared pointer still takes up memory?
i.e. if I were to declare billions of different pointers to NULL, it would still use up memory (and hence I would have a need to delete the pointer itself).
of course it does... a pointer is just a location in memory containing an address into the virtual memory; in fact doubling the virtual memory space will double the space your pointers occupy (but not necessarily the space occupied by the data they point to).
How would I delete the pointer?
as I said, it depends on how you created the pointer. if you for some reason allocated it on the heap, then you should free that memory as well.
A pointer is simply a variable, like an int. On a 32-bit CPU a pointer will consume 4 bytes of storage, 8 bytes on a 64-bit system.
So if you declare a billion pointers to NULL, you have essentially declared a billion *int*s.
The thing that makes it a pointer is only the fact that the value stored in that variable just happens to be the address of some place in memory. When you call delete on a pointer, you are freeing the memory at that address stored in the pointer, not the memory used by the pointer variable itself.
You can not delete the pointer itself - only pointed by it data.
Pointer is destroyed when its scope is ended:
{
int *p = NULL;
}
After closing bracket the pointer is distroyed.
The question is what is deleting a pointer. If you assign new pointer to the same variable you don't need to worry about deleting billions. If you allocate space for pointer, you surely should delete them, but then again it will be pointer to pointers, so it's pointers, not pointer that is getting deleted. If you allocate space statically (like declaring array of billions of pointers) you can't really delete it.
In short, I think you need a better understanding of the nature of pointer.
Using C++:
I currently have a method in which if an event occurs an object is created, and a pointer to that object is stored in a vector of pointers to objects of that class. However, since objects are destroyed once the local scope ends, does this mean that the pointer I stored to the object in the vector is now null or undefined? If so, are there any general ways to get around this - I'm assuming the best way would be to allocate on the heap.
I ask this because when I try to access the vector and do operations on the contents I am getting odd behavior, and I'm not sure if this could be the cause or if it's something totally unrelated.
It depends on how you allocate the object. If you allocate the object as an auto variable, (i.e. on the stack), then any pointer to that object will become invalid once the object goes out of scope, and so dereferencing the pointer will lead to undefined behavior.
For example:
Object* pointer;
{
Object myobject;
pointer = &myobject;
}
pointer->doSomething(); // <--- INVALID! myobject is now out of scope
If, however, you allocate the object on the Heap, using the new operator, then the object will remain valid even after you exit the local scope. However, remember that there is no automatic garbage collection in C++, and so you must remember to delete the object or you will have a memory leak.
So if I understand correctly you have described the following scenario:
class MyClass
{
public:
int a;
SomeOtherClass b;
};
void Test()
{
std::vector<MyClass*> v;
for (int i=0; i < 10; ++i)
{
MyClass b;
v.push_back(&b);
}
// now v holds 10 items pointers to strange and scary places.
}
This is definitely bad.
There are two primary alternatives:
allocate the objects on the heap using new.
make the vector hold instances of MyClass (i.e. std::vector<MyClass>)
I generally prefer the second option when possible. This is because I don't have to worry about manually deallocating memory, the vector does it for me. It is also often more efficient. The only problem, is that I would have to be sure to create a copy constructor for MyClass. That means a constructor of the form MyClass(const MyClass& other) { ... }.
If you store a pointer to an object, and that object is destroyed (e.g. goes out of scope), that pointer will not be null, but if you try to use it you will get undefined behavior. So if one of the pointers in your vector points to a stack-allocated object, and that object goes out of scope, that pointer will become impossible to use safely. In particular, there's no way to tell whether a pointer points to a valid object or not; you just have to write your program in such a way that pointers never ever ever point to destroyed objects.
To get around this, you can use new to allocate space for your object on the heap. Then it won't be destroyed until you delete it. However, this takes a little care to get right as you have to make sure that your object isn't destroyed too early (leaving another 'dangling pointer' problem like the one you have now) or too late (creating a memory leak).
To get around that, the common approach in C++ is to use what's called (with varying degrees of accuracy) a smart pointer. If you're new to C++ you probably shouldn't worry about these yet, but if you're feeling ambitious (or frustrated with memory corruption bugs), check out shared_ptr from the Boost library.
If you have a local variable, such as an int counter, then it will be out of scope when you exit the function, but, unless you have a C++ with a garbage collector, then your pointer will be in scope, as you have some global vector that points to your object, as long as you did a new for the pointer.
I haven't seen a situation where I have done new and my memory was freed without me doing anything.
To check (in no particular order):
Did you hit an exception during construction of member objects whose pointers you store?
Do you have a null-pointer in the container that you dereference?
Are you using the vector object after it goes out of scope? (Looks unlikely, but I still have to ask.)
Are you cleaning up properly?
Here's a sample to help you along:
void SomeClass::Erase(std::vector<YourType*> &a)
{
for( size_t i = 0; i < a.size(); i++ ) delete a[i];
a.clear();
}