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

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

Related

Is it legal to assign heap allocated class object to stack allocated object in C++?

In C++ we can assign heap allocated object of class to stack allocated object by dereferencing it. It looks like there is no problem and it works as expected even destructor works well, but is it good or bad to write code like this?
#include <iostream>
class cls {
public:
cls(int n) : pInt{new int{n}} {
std::cout << "Constructor\n";
}
int *pInt;
~cls() {
std::cout << "Destructor\n";
delete pInt;
}
};
int main() {
cls *hObj = new cls{100};
cls sObj = *hObj;
}
They copying is okay, but note that the compiler-generated copy-constructor will do a shallow copy.
That means, the pointer is copied, not what it points to. That leads you to have two objectd with the exact same pInt pointer, pointing to the exact same memory. And you can only delete that memory once.
This is the reason for the rules of three, five and zero.
As for why this program seems to work, it's because you don't delete hObj. Only the sObj destructor will run, so in the code as currently shown there's only one delete pInt.
If you add delete hObj before program termination, then both destructors will delete the same memory, and you will have undefined behavior (and very likely a crash).

How do you access variables that are allocated on the heap in C++ even after leaving the scope?

I'm having issues understanding the new keyword in C++. I understand that in order to not have memory popped off from stack after leaving scope; you can store it on heap. However in this example I get an error saying "identifier p is undefined"
#include <iostream>
#include <string>
class Person {
public:
int age;
std::string name;
Person() {
}
Person(int a, std::string n): age(a), name(n){}
};
int main() {
{
Person* p = new Person(5, "bob");
}
std::cout << (*p).age;
}
As you can see in my main function I've created another scope where I create a Person object on heap, from what I know the object will still exist after leaving the curly brackets, but then why is it not recognizing object p?
I've tried derefrencing p but the error remains the same.
Any help would be great!
Thanks
You are correct that the object still exists since you never deleted it. That is only half the issue though. The name p is local to the nested scope you declared it in. Once you exit that scope, p is destroyed and you can no longer access the object that you created.
What you would need would be
int main()
{
Person* p;
{
p = new Person(5, "bob");
}
std::cout << (*p).age;
}
and now you can access p since it was declared in main's scope.
Person* p is a Pointer* type object with automatic storage (a "local variable"). That pointer, like any object with automatic storage, only exists until the end of the scope it was declared in. Once you reach the closing } of the block scope you made, there is no such thing as p anymore, that pointer has stopped existing.
While p doesn't exist, what it used to point to still does. Your Person is leaked and gone. Without a pointer or reference to it, there's no way to get it back and no way to clean it up. Make sure to keep p or another pointer to it until you delete it.
Moving the declaration of Person* p to outside of the scope (or removing the artificial scope entirely) will solve this problem. In that case, p's lifetime is linked to main's scope and will still exist by the time you try to std::cout it's age member.
Consider using smart pointers to at least avoid leaks like this. std::unique_ptr<Person> p would automatically delete the Person when the last (and only) pointer ceases existing.
The object is still there, and if you do not delete it you have a memory leak. If you want to access it elsewhere you need to keep a reference to it (reference in the general sense, ie pointer or reference).
The variable however, is only accesible in the scope where it is declared. You could for example fix it by doing:
int main() {
Person* p;
{
p = new Person(5, "bob");
}
std::cout << (*p).age;
delete p;
}
The problem is when you create a variable between curly braces it will have a block scope.
And it will die after the block ends(the pointer p itself which is 32/64 bit value depending on your machine). and the memory allocated by new is still in
the heap but the pointer itself isn't.(which will cause a memory leak).
I don't know what do you want to do exactly but you can do
int main() {
Person * ptr;
{
Person* p = new Person(5, "bob");
ptr = p;
}
std::cout << (*ptr).age;
//free the memory if you will not use it anymore
delete ptr;
}
Then you can use ptr to point to the block create by new.
Person* p
the pointer is used to store the memory address of the object, memory has been assigned on the heap to store the member variables, you have to explicitly use delete which calls the default destructor to destroy that object, since p is used in the block, you cannot call it from outside.

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

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.

Delete pointer and object

How do I delete a pointer and the object it's pointing to?
Will the code below delete the object?
Object *apple;
apple = new Object();
delete apple;
And what happens if the pointer is not deleted, and gets out of scope?
Object *apple;
apple = new Object();
This might be a very basic question, but I'm coming from Java.
Your first code snippet does indeed delete the object. The pointer itself is a local variable allocated on the stack. It will be deallocated as soon as it goes out of scope.
That brings up the second point--if the pointer goes out of scope before you deallocate the object you allocated on the heap, you will never be able to deallocate it, and will have a memory leak.
Hope this helps.
Hello and welcome to C++ land! You will love how much you hate it (or something like that). C++, while appearing to be similar to java in untrained eyes might look similar, is actually quite different semantically. Lets see how these semantics play out in c++ in regards to your question. First lets take a class:
class Foo {
public:
Foo() { std::cout << "In constructor\n"; }
~Foo() { std::cout << "In destructor\n"; }
};
Foo here is just a representative of any class you might want to use. Lets see what happens when we create and play with a normal Foo object:
{
Foo bar;
do_stuff(bar);
}
If we were to run code that looked like this, we would see:
In constructor
In destructor
This is because, when an object is created, it is constructed using the constructor. When it goes out of scope, the destructor is called (~Foo in our code) which deconstructs (or destroys) the object. This is actually a fairly common and powerful feature in C++ (known as RAII, as opposed to other forms of returning memory to the system, such as Garbage Collection). Armed with this new knowledge, lets see what happens when we play with a pointer to Foo:
{
Foo *bar = new Foo();
some_more_stuff(bar);
}
What happens here is we would see:
In constructor
This is because of how pointers are allocated versus how variables are allocated. The way pointers are allocated, they don't actually go out of scope normally, but their contents do. This is known as a dangling pointer. For a better example, take a look at this:
#include <iostream>
int* get_int() {
int qux = 42;
int *foo = &qux;
return foo;
}
int main() {
int *qazal = get_int();
std::cout << *qazal;
}
Thanks to modern operating systems, this memory will still be returned when the program finishes, but not during the running of the program. If we were to delete the pointer (in the same scope it was created) via delete, then that memory will actually be returned to the operating system at that time.
When you call delete on a pointer it frees the memory of the thing pointed to. In other words you don't need to free the memory that makes up the pointer variable, just the thing that is pointed to. So your code:
Object *apple;
apple = new Object();
delete apple;
correctly deletes the object and there will be no memory leak.
If you don't call delete and the variable goes out of scope then you'll have a memory leak. These can be difficult to track down, so it's advisable to use a smart pointer class.
Operator delete deletes an object pointed to by the pointer that previously was allocated with operator new.
The pointer itself is not changed and even will have the same value as before the calling the operator. However its value becomes invalid after deleteing the object.
If the pointer itself is a local variable it will be destroyed after the control leaves the declaration region of the pointer.
If the pointer has the static storage duration then it will be destroyed when the program finishes its execution.
Take into account that you can use smart pointers instead of raw pointers.
For example
std::unique_ptr<Object> apple( new Object() );
in this case you need not to call delete It is the smart pointer that will do all the work itself.
Will the code below delete the object?
Yes, it will. But the pointer isn't deleted and accidentally using the pointer after deletion will lead to error.
And what happens if the pointer is not deleted, and gets out of scope?
Memory leak will happen.

Organization of a c++ program in memory - stack and heap [duplicate]

This question already has answers here:
What and where are the stack and heap?
(31 answers)
Closed 8 years ago.
I am learning c++ and would like to know how a program like this is organized in primary-memory. I understand that there are a stack (with stackframes) and a heap. And I know that dynamically allocating something allocates it on the heap. This is done by operators like malloc or new. But I cant see them in this small c++ program.
The program consists of a main-class and a class named MyClass. This class has:
one constructor
one member variable (int)
one member-function
The main-class defines an object to Myclass and as well defines a pointer to this object.
SO - how are all this organized in memory?
#include <iostream>
using namespace std;
class MyClass {
int i;
public:
MyClass(int n) {
i = n;
}
int get_nmbr() {
return this->i;
}
};
int main() {
MyClass myClass(100), *p;
cout << myClass.get_nmbr() << endl;
p = &myClass;
cout << p;
return 0;
}
Let's go through this line by line.
int main() {
A new function starts with this line, and therewith a new scope.
MyClass myClass(100), *p;
Two things happen here. One, a variable myClass is declared within the function's scope, which makes it a local variable and thus it's allocated on the stack. The compiler will emit machine instructions that reserve enough space on the stack (usually by bumping the sp stack pointer register), and then a call to the class constructor executes. The this pointer passed to the constructor is the base of the stack allocation.
The second variable p is just a local pointer, and the compiler (depending on optimizations) may store this value on the local stack or in a register.
cout << myClass.get_nmbr() << endl;
Call the get_nmbr() method of the local myClass instance. Again, the this pointer points to the local stack frame allocation. This function finds the value of instance variable i and returns it to the caller. Note that, because the object is allocated on the stack frame, i lives on the stack frame as well.
p = &myClass;
Store the address of the myClass instance in variable p. This is a stack address.
cout << p;
return 0;
}
Print out the local variable p and return.
All of your code is only concerned with stack allocations. The result of that is that when the function's scope is left/closed at execution time (e.g. the function returns), the object will be automatically "destructed" and its memory freed. If there are pointers like p that you return from that function, you're looking at a dangling pointer, i.e. a pointer that points at an object that's freed and destructed. (The behavior of a memory access through such a dangling pointer is "undefined" as per language standard.)
If you want to allocate an object on the heap, and therefore expand its lifetime beyond the scope wherein it's declared, then you use the new operator in C++. Under the hood, new calls malloc and then calls an appropriate constructor.
You could extend your above example to something like the following:
{
MyClass stackObj(100); // Allocate an instance of MyClass on the function's stack frame
MyClass *heapObj = new MyClass(100); // Allocate an instance of MyClass from the process heap.
printf("stack = %p heap = %p\n", stackObj, heapObj);
// Scope closes, thus call the stackObj destructor, but no need to free stackObj memory as this is done automatically when the containing function returns.
delete heapObj; // Call heapObj destructor and free the heap allocation.
}
Note: You may want to take a look at placement new, and perhaps auto pointers and shared pointers in this context.
First things first. In C++ you should not use malloc.
In this program, all memory used is on the stack. Let's look at them one at a time:
MyClass myClass(100);
myClass is an automatic variable on the stack with a size equal to sizeof(MyClass);. This includes the member i.
MyClass *p;
p is an automatic variable on the stack which points to an instance of MyClass. Since it's not initialized it can point anywhere and should not be used. Its size is equal to sizeof(MyClass*); and it's probably (but not necessarily) placed on the stack immediately after myClass.
cout << myClass.get_nmbr() << endl;
MyClass::get_nmbr() returns a copy of the member i of the myClass instance. This copy is probably optimized away and therefore won't occupy any additional memory. If it did, it would be on the stack. The behavior of ostream& operator<< (int val); is implementation specific.
p = &myClass;
Here p is pointing to a valid MyClass instance, but since the instance already existed, nothing changes in the memory layout.
cout << p;
Outputs the address of myClass. Once again the behavior of operator<< is implementation specific.
This program (kind of) visualizes the layout of the automatic variables.
You have myClass object and pointer p (declared as MyClass *) created on stack. So. within myClass object the data members i also gets created on stack as part of myClass object. The pointer p is stored on stack, but you are not allocating for p, rather you are having p assigned to address of myClass object which is already stored on stack. So, no heap allocation here, at least from the program segment that you posted.
myClass is allocated on the stack. This program doesn't use heap exept maybe for allocating a stdout buffer behind the scenes. When myClass goes out of scope (e.g. when main returns or throws an exception), myClass is destructed and the stack is released, making p invalid.
In modern C++ it is considered safer to use smart pointers, such as the shared_ptr, instead of raw pointers.
To allocate myClass on the heap you could write:
#include <memory>
int main() {
std::shared_ptr<MyClass> p (new MyClass (100)); // Two heap allocations: for reference counter and for MyClass.
auto p2 = std::make_shared<MyClass> (101); // One heap allocation: reference counter and MyClass stored together.
return 0;
}