C++ - Shallow copying a pointer. Why is this code working? - c++

To my understanding of the subject:
A shallow copy is when the non-pointer types of an object are copied to another object. Shallow copies can't be done when an object has pointers because, the object being copied will get the address of that pointer, and when either of the two objects are deleted, the other will be left dangling since they were pointing to the same location in memory.
A deep copy is used when pointers are involved because it reserves a space separate from the original object's space and just copies the contents from one memory location to another. This way, when one of the objects is deleted, teh other isn't left dangling.
That said, I would like to know why this program is working even though I've done a shallow copy of a pointer
struct aStruct {
int *i;
aStruct(int *p) : i(p) {
cout << "Created aStruct" << endl;
}
aStruct(const aStruct &s) {
cout << "Copying aStruct" << endl;
i = s.i;
}
aStruct &operator=(const aStruct &s) {
cout << "Assigning aStruct" << endl;
i = s.i;
return *this;
}
};
int main() {
int *x = new int(3);
aStruct s1(x);
aStruct s2 = s1;
int *y = new int(4);
aStruct s3(y);
s3 = s1;
}
s1, s2, and s3 all have their variable i pointing to the same place. So when the end of the main() function is reached and one of them is destroyed, shouldn't the others be left dangling causing an error? My program works fine. Could someone please be kind enough to explain this to me?
Thanks all

You are copying the pointer, not the data. Each object here is an object in its own right, additionally, you seem to be under the impression that C++ is garbage-collected. it is not (except in some uncommon implementations)
Your program basically leaks memory and is only cleaned up by virtue of the OS releasing whatever your process consumed after it terminated. Consequently, all your pointers are pointing to perfectly valid memory throughout the lifetime of your application.

Unfortunately, there is no concept of Deep and Shallow pointers in C++. The notion of references in Java and C# is different from pointers in C++.
You should read on
What are the differences between a pointer variable and a reference variable in C++?
What is a smart pointer and when should I use one?
What is The Rule of Three?
Take it this way, in C++, Pointers refers to whatever object is in the memory location it, the pointer is pointing to.
So, what you are doing is copying the allocated location into your constructor into the object... When the destructor runs, of cause the entire object is freed from memory (dead), including the pointer int* i that is a data member. But the memory location allocated by new isn't freed until someone calls that same location with a delete.

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

How memory is deallocated in shared_ptr via the operator=?

I am a beginner to c++, I was learning the concept of shared_ptr.
I also understood that
Several shared_ptr objects may own the same object and the object is destroyed and its memory deallocated when either of the following happens:
1.the last remaining shared_ptr owning the object is destroyed;
2.the last remaining shared_ptr owning the object is assigned another pointer via operator= or reset().
But when I tried to execute a sample program
class Rectangle {
int length;
int breadth;
public:
Rectangle(int l, int b)
{
length = l;
breadth = b;
}
int area()
{
return length * breadth;
}
};
int main()
{
shared_ptr<Rectangle> P1(new Rectangle(10, 5));
cout << P1->area() << endl;
shared_ptr<Rectangle> P2;
P2 = P1; //how is this possible
// This'll print 50
cout << P2->area() << endl;
// This'll now not give an error,
cout << P1->area() << endl;
cout << P1.use_count() << endl;
return 0;
}
After "P2=P1" the memory allocated to P1 has to be deallocated right?
But still we can print P1->area().
Please explain how this is happening?
2.the last remaining shared_ptr owning the object is assigned another pointer via operator= or reset().
Yes.
After "P2=P1" the memory allocated to P1 has to be deallocated right?
No. It could happen to P2 if it pointed to something. Not P1.
The logic behind the rule (2) is that the assignment overwrites the value of the first operand, so the first operand will no longer point to what it used to. If it was the last pointer to something, then nothing will point to that anymore, and it can be deleted.
What you learned about destruction of shared pointers is correct. But here, you are not destroying P1. Instead, you are assigning P1 to P2. The implementation of shared_ptr has an overloaded copy assignment operator allowing for this operation and making it correct.
Through that overloaded implementation, P2 is now a shared pointer pointing to the same object as P1 - both pointers access the same object, so you are printing the same areas. Both of them exist in a valid state and as you see, the count of pointers that manage that Rectangle object is 2.
Defining the overloaded = is aligned with the concept of shared_ptr - there are multiple pointers pointing to (owing) the same object. If you want to see a contrasting implementation, look up the unique_ptr - this is a smart pointer that assumes only one pointer has an ownership of the object. It also has an overloaded assignment operator, but using it would invalidate P1 (to my knowledge it would set it to nullptr so it would still be in a valid state, just not pointing to anything). P2 would be the only owner of the Rectangle. Worth trying, for better understanding.
You can find more on the shared_ptr functionality here.

C++ accessing object on heap after end of pointer scope

I've been reading various questions and answers about pointers in C++ on SO but I still am fundamentally not understanding something.
I've read that pointers allow for dynamic memory allocation, by not actually deleting an object until explicitly told to do so. This I understand, but what I don't understand is how an object on the heap is ever referred to again after the scope of its pointer ends.
See code below.
{
myClass* x = new myClass();
}
// How to access the object that x points to here?
I understand that at the end of the scope, x (the pointer itself) no longer exists, but the object (that the pointer was pointing to) still does exist on the heap.
My question is: How is that address in memory ever accessed again if the pointer that points to that address in memory no longer exists?
How is that address in memory ever accessed again if the pointer that points to that address in memory no longer exists?
If the pointer value is not stored elsewhere, the object is "leaked" and becomes inaccessible. The object will continue to exist until the process terminates, at which point the operating system will reclaim the memory used by the object.
what I don't understand is how an object on the heap is ever referred to again after the scope of its pointer ends.
The pointer would have to be copied somewhere else. For example, you might put the pointer into a vector or a map before the local pointer goes out of scope, and then the object can still be accessed through the pointer stored in the vector/map:
int main() {
std::vector<myClass *> objects;
{
myClass *x = new myClass();
objects.push_back(x);
}
// The heap-allocated object can be accessed through objects[0] now
objects[0]->doSomething();
// Don't forget to clean up (or use smart pointers)
for (auto i : objects) { delete i; }
return 0;
}
Note that it's useful to learn how to use raw pointers when learning C++, but at some point you should switch to smart pointers like std::unique_ptr, which will automatically delete the pointed-to object for you:
{
std::unique_ptr<myClass> x{new myClass()};
}
// The myClass object has already been deleted by the smart pointer
Here you can find a small example that shows the differences between (1) allocation without proper deletion, (2) allocation with proper deletion, and (3) allocation using a smart pointer that deletes itself when it goes out of scope. Just run the program to see that the first example leaks memory.
#include <iostream>
#include <memory>
class A
{
public:
A(std::string name) : name_(name)
{
std::cout << "My name is " << name_ << ", and I make mess...\n";
}
~A()
{
std::cout << "My name is " << name_ << ", and I clean up...\n";
}
private:
std::string name_;
};
int main()
{
// 1. Leaks.
A* a0;
a0 = new A("a0");
// 2. Does not leak.
A* a1;
a1 = new A("a1");
delete a1;
// 3. Does not leak.
std::unique_ptr<A> a2 = std::make_unique<A>("a2");
return 0;
}

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

Deconstructing a *Thing

I'm sure this is answered somewhere, but I'm lacking the vocabulary to formulate a search.
#include <iostream>
class Thing
{
public:
int value;
Thing();
virtual ~Thing() { std::cout << "Destroyed a thing with value " << value << std::endl; }
};
Thing::Thing(int newval)
{
value = newval;
}
int main()
{
Thing *myThing1 = new Thing(5);
std::cout << "Value 1: " << myThing1->value << std::endl;
Thing myThing2 = Thing(6);
std::cout << "Value 2: " << myThing2.value << std::endl;
return 0;
}
Output indicates myThing2 was destroyed, my myThing1 was not.
So... do I need to deconstruct it manually somehow? Is this a memory leak? Should I avoid using the * in this situation, and if so, when would it be appropriate?
The golden rule is, wherever you use a new you must use a delete. You are creating dynamic memory for myThing1, but you never release it, hence the destructor for myThing1 is never called.
The difference between this and myThing2 is that myThing2 is a scoped object. The operation:
Thing myThing2 = Thing(6);
is not similar at all to:
Thing *myThing1 = new Thing(5);
Read more about dynamic allocation here. But as some final advice, you should be using the new keyword sparingly, read more about that here:
Why should C++ programmers minimize use of 'new'?
myThing1 is a Thing* not a Thing. When a pointer goes out of scope nothing happens except that you leak the memory it was holding as there is no way to get it back. In order for the destructor to be called you need to delete myThing1; before it goes out of scope. delete frees the memory that was allocated and calls the destructor for class types.
The rule of thumb is for every new/new[] there should be a corresponding delete/delete[]
You need to explicitly delete myThing1 or use shared_ptr / unique_ptr.
delete myThing1;
The problem is not related to using pointer Thing *. A pointer can point to an object with automatic storage duration.
The problem is that in this statement
Thing *myThing1 = new Thing(5);
there is created an object new Thing(5) using the new operator. This object can be deleted by using the delete operator.
delete myThing1;
Otherwise it will preserve the memory until the program will not finish.
Thing myThing2 = Thing(6);
This line creates a Thing in main's stack with automatic storage duration. When main() ends it will get cleaned up.
Thing *myThing1 = new Thing(5);
This, on the other hand, creates a pointer to a Thing. The pointer resides on the stack, but the actual object is in the heap. When the pointer goes out of scope nothing happens to the pointed-to thing, the only thing reclaimed is the couple of bytes used by the pointer itself.
In order to fix this you have two options, one good, one less good.
Less good:
Put a delete myThing1; towards the end of your function. This will free to allocated object. As noted in other answers, every allocation of memory must have a matching deallocation, else you will leak memory.
However, in modern C++, unless you have good reason not to, you should really be using shared_ptr / unique_ptr to manage your memory. If you had instead declared myThing1 thusly:
shared_ptr<Thing> myThing1(new Thing(5));
Then the code you have now would work the way you expect. Smart pointers are powerful and useful in that they greatly reduce the amount of work you have to do to manage memory (although they do have some gotchas, circular references take extra work, for example).