Stack memory allocation and deallocation mechanism - c++

If I pass by value as an argument to a particular function, then will that function deallocate memory of this parameter when the function execution ends?
If I pass a pointer or reference as argument, what happens if function deallocates memory of the pointer argument? Will it affect to the variable outside of function?

In the first case memory will be "deallocated" (actually stack pointer will be increased). If this is not POD type variable destructor is called, so the memory will be deallocated from heap if it was allocated there.
In the second case value referenced by pointer won't be deallocated - only memory for pointer will be deallocated.

For point 1, it depends on the type of argument. Passing e.g. a 'string' by value will do an implicit copy, and the memory that copy uses will be deallocated when the variable (function parameter) goes out of scope. This won't automatically happen for your own types - you'll need to set up construction and destruction properly.
For the second - yeah, deallocating using a pointer will affect the memory it addresses - both inside the function and outside.
To clarify the second point:
void func(char *someMemory) {
delete[] someMemory;
}
//...
char *myArray = new char[100];
func(myArray);
...will delete the allocated memory - using myArray after the call to func is BAD.

If you pass a value or a pointer on the stack the memory required to hold that value is allocated on the stack...
The way the stack works you can keep "allocating" more memory but it has to be "freed" in reverse order.
So:
void f(int *ptr, int v)
{
// Do something
}
When you call f() the value of ptr and v are "pushed" on the stack, that is enough memory is magically created to hold those values. When the function returns the stack is adjusted the other way, in a sense they are "popped" from the stack.
This pushing and popping has no effect on the original pointer or value. So:
ptr++;
Will not effect the value of the pointer held by the calling function.
If you dereference, *ptr, the pointer you are accessing the same data that is visible from outside the function. If you free() the pointer this impacts what is seen from outside the function. So when you pass a pointer there are no copies made of the original data the pointer is pointing to but there is a copy made of the actual pointer. The pointer is passed by value.

Related

Pointer is corrupting data for no good reason in C++ [duplicate]

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

Return value in a function not working? [duplicate]

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

C++ deleting a pointer itself instead of deleting the pointed-to-data

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.

Pointer validity after stack unwinding

In C++ does a pointer remains valid after stack unwinding or not?
It depends on the storage of the pointed-to object. If that object was stack-allocated then the pointer surely becomes invalid - stack unwinding will properly destroy the object. If the object was heap-allocated the pointer only becomes invalid if there's some RAII variable that deallocates the object during stack unwinding.
It depends on what your pointer is pointing to. If it points to heap memory, it still remains valid. If it points to stack memory, it becomes invalid.
No. With stack Unwinding all variables/pointers that are declared in the scopes of the unwounded part of the stack get destroyed.
Also, the rule takes in to consideration the Storage Type of the variables.
for eg: A static variable retains its value between function calls, which means it is not destroyed during stack unwinding. This is due to the fact that Static variable are not stored on the stack but on the BSS or Data Segments.
Local variables(Auto storage type) created on stack inside a function will always be destroyed when function returns and stack unwinding takes place.
Pointers allocated with memory on heap will not be destroyed on stack unwinding because they are allocated on Heap and not stack.
One important rule to remember is NEVER return pointers or references to local variables inside a function. The pointer or reference will contain garbage values.
Consider some examples:
void* f1a()
{
void* p = malloc(10);
return p;
}
...is the same as...
void* f1b()
{
return malloc(10);
}
That's fine, as the pointers are to the heap and thus independent of the stack, function calls and programmatic scopes. The pointer value is copied as the function returns.
int* f2()
{
int x;
return &x; // pointer to x - about to become invalid!
}
The above returns a pointer to a variable x on the stack, which will be reclaimed (x lost) when the function returns.
just to state one extra thing which i feel is important
say we have this statement
obj* objptr = new obj(9) //allocate memory on heap and use constructor
if here exception occurs..
the memory heap is relased back....ie no memory leak...
the reason is....
not because of stack unwinding...but because the way the new operator is converted into the following generated code
the try catch statement are implemented in new operator...something like this...
void * operator new(size_t s)
{
try
{
void * ptr=new(malloc (s))sample(); //placement new
ptr->...
}
catch(..)
{
operator delete(ptr); //<= notice here so if an exception occur then first it is caught here which releases the memory
}
}
however if within the object some memory allocation is done that still doesnt get freed..

the scope of a pointer?

Ok, so I did find some questions that were almost similar but they actually confused me even more about pointers.
C++ Pointer Objects vs. Non Pointer Objects
In the link above, they say that if you declare a pointer it is actually saved on the heap and not on the stack, regardless of where it was declared at. Is this true ?? Or am I misunderstanding ??? I thought that regardless of a pointer or non pointer, if its a global variable, it lives as long as the application. If its a local variable or declared within a loop or function, its life is only as long as the code within it.
The variable itself is stored on the stack or DATA segment, but the memory it points to after being allocated with new is within the heap.
void main()
{
int* p; // p is stored on stack
p = new int[20]; // 20 ints are stored on heap
}
// p no longer exists, but the 20 ints DO EXSIST!
Hope that helps.
void func()
{
int x = 1;
int *p = &x;
}
// p goes out of scope, so does the memory it points to
void func()
{
int *p = new int;
}
// p goes out of scope, the memory it points to DOES NOT
void func()
{
int x = 1;
int **pp = new int*;
*pp = &x;
}
// pp goes out of scope, the pointer it points to does not, the memory it points to does
And so forth. A pointer is a variable that contains a memory location. Like all variables, it can be on the heap or the stack, depending on how it's declared. It's value -- the memory location -- can also exist on the heap or the stack.
Typically, if you statically allocate something, it's on the stack. If you dynamically allocate something (using either new or malloc) then it's on the heap. Generally speaking you can only access dynamically allocated memory using a pointer. This is probably where the confusion arises.
It is necessary to distinguish between the pointer (a variable that holds a memory location) and the object to which the pointer points (the object at the memory address held by the pointer). A pointer can point to objects on the stack or on the heap. If you use new to allocate the object, it will be on the heap. The pointer can, likewise, live on the heap. If you declare it in the body of a function, then it will be a local variable and live in local storage (i.e. on the stack), whereas if it is a global variable, it will live somewhere in your application's data section. You can also have pointers to pointers, and similarly one can allocate a pointer on the heap (and have a pointer-to-a-pointer pointing to that), etc. Note that while I have referenced the heap and stack, the C++ only mentions local/automatic storage and dynamic storage... it does not speak to the implementation. In practice, though, local=stack and dynamic=heap.
A pointer is a variable containing the address of some other object in memory. The pointer variable can be allocated:
on the stack (as a local auto variable in a function or statement block)
statically (as a global variable or static class member)
on the heap (as a new object or as a class object member)
The object that the pointer points to (references) can likewise be allocated in these three places as well. Generally speaking, though, a pointed-to object is allocated using the new operator.
Local variables go out of scope when the program flow leaves the block (or function) that they are declared within, i.e., their presence on the stack disappears. Similarly, member variables of an object disappear when their parent object goes out of scope or is deleted from the heap.
If a pointer goes out of scope or its parent object is deleted, the object that the pointer references still exists in memory. Thus the rule of thumb that any code that allocates (news) an object owns the object and should also delete that object when it's no longer needed.
Auto-pointers take some of the drudgery out of the management of the pointed-to object. An object that has been allocated through an auto_ptr is deleted when that pointer goes out of scope. The object can be assigned from its owning auto_ptr to another auto_ptr, which transfers object ownership to the second pointer.
References are essentially pointers in disguise, but that's a topic for another discussion.
I thought that regardless of a pointer
or non pointer, if its a global
variable, it lives as long as the
application. If its a local variable
or declared within a loop or function,
its life is only as long as the code
within it.
That's true.
they say that if you declare a pointer
it is actually saved on the heap and
not on the stack
That's wrong, partially. You can have a pointer on the heap or the stack. It's a matter of where and how you declare it.
void main()
{
char c = 0x25;
char *p_stack = &c; // pointer on stack
StructWithPointer struct_stack; // stack
StructWithPointer *struct_heap = new StructWithPointer(); // heap, thus its pointer member "p" (see next line) is also on the heap.
struct_heap->p = &c; // pointer on heap points to a stack
}
... and, a compiler might decide to use a register for a pointer!
Looks like you need to grab the classic K&R C book and read through chapters 4 & 5 for thorough understanding of the differences between declaration and definition, scope of a variable and about pointers.