I have the following question.
If
int a = 5;
and
int *b = new int(a);
and then I do
delete b;
it will delete the object that b is pointing to if I am not mistaken. What I don't understand is what happens to b?
Does b remain a pointer pointing to the address where the object created by new used to live?
then I do delete b; it will delete the object a that b is pointing to
It will delete the object that b is pointing to yes, but that object has nothing to do with the object a (other than they both have the same value).
What I dont understand is what happens to b? Does b remain a pointer pointing to the adress where the object created by new used to live.
That's exactly what happens to b i.e. nothing happens to it. delete only affects the dynamic memory management and pointed object (calling its destructor). The pointer variables value itself won't be changed, but is a dangling pointer afterwards.
Yes, b remains a valid pointer - it's simply the address to which it points that becomes invalid. Declaring
int* b;
will reserve storage for a variable b (albeit unitialized), in just the same way as
int c;
reserves space for storing an integer.
However, your b never pointed to the address of a - this is not what new int(a) does. Your b was a pointer to an address containing a copy of the value of a.
Your understanding is completely wrong. First, delete b; will call the destructor for the type e (a no-op in the case of a primitive type like int) but then it will crash because there will be an attempt to deallocate the object at b, but since this is an object with automatic storage duration the attempt will fail in a major way.
Also, the initialization of b would need to be "int * b = &a;", trying to assign an int to a int * will produce a compile-time error.
When you delete an object by pointer, two things happen:
The memory that has previously been allocated to the object becomes available for re-allocation, and
The pointer becomes invalid (reference: what is dangling pointer?).
Once you call delete b you can reuse b to point to another object, like this
b = new int(123);
or like this
int a(123);
b = &a; // Obviously, you can't delete b after this
or you can set it to nullptr, like this
b = nullptr;
but you cannot dereference the pointer, because it would cause undefined behavior.
Does b remain a pointer pointing to the adress where the object created by new used to live?
Usually, that is exactly what happens - the value of b remains unchanged. However, there is no standard-compliant way to find out, because C++ implementation is free to set it in whichever way it likes. For example, the pointer could be set to a trap representation, so merely printing the value of the pointer would cause a crash.
You can't delete memory that is not allocated by new.
You can't apply deleteat any pointer you didn't initialize with new.
delete b would exhibit undefined behavior, as the value of b was not obtained with new expression.
Thanks,
Raghava
Related
Here's the line of code:
A a = static_cast<A>(*(new A)); // ?
It compiles fine on 64bit clang at least.
But where is the memory actually allocated and what happens to variable a?
Besides there's no static cast needed, the memory allocated with new A simply leaks. You have lost access to that pointer and can never delete it properly anymore.
But where is the memory actually allocated and what happens to variable a?
Variable a is destroyed as soon it leaves scope as usual.
A a = static_cast<A>(*(new A)); // ?
This does the following.
(new A) // allocate a new A on the heap
*(new A) // the type is now A instead of *A
static_cast<A>(*(new A)) // makes it into an type A from type A in an potentially unsafe way (here it is a no-op as they are the same type)
A a = static_cast<A>(*(new A)); // copies the (default) value of A to a
; // leaks the allocted A as the last reference to it disappear.
I'm going to answer this question on the assumption that this line of code appears inside a function. If it appears elsewhere, the bit about the "stack" is inaccurate but everything else is still accurate.
This line of code compiles to four operations, which we can write as their own lines of C++ to make things clearer. It makes two allocations, in two different places, and one of them is "leaked".
A a;
{
A *temp = new A;
a = *temp;
}
The first operation allocates space for an object of type A on the "stack", and default-initializes it. This object is accessible through the variable a. It will be automatically destructed and deallocated no later than when the function returns; depending on surrounding context, this might happen earlier, but in no case while the variable a is in scope.
The second operation allocates space for another object of type A, but on the "heap" instead of the "stack". This object is also default-initialized. The new operator returns a pointer to this object, which the compiler stores in an temporary variable. (I gave that variable the name temp because I had to give it some name; in your original code the temporary is not accessible by any means.) This object will only ever be deallocated if, at some point in the future, the pointer returned by new is used in a delete operation.
The third operation, finally, copies the contents of the object on the heap, pointed to by temp, into the object on the stack, accessible via the variable a. (Note: the static_cast<A>(...) that you had written here has no effect whatsoever, because *temp already has the type A. Therefore, I took it out.)
Finally, the temporary variable holding the pointer to the object on the heap is discarded. The object on the heap is not deallocated when this happens; in fact, it becomes impossible for anything ever to deallocate it. That object is said to have leaked.
You probably wanted to write either
A a;
which allocates an object on the stack and does nothing else, or
// note: C++11 only; C++03 equivalent is std::shared_ptr<A> a(new A());
auto a = std::make_shared<A>();
which allocates an object on the heap and arranges to reference-count it, so that it probably won't leak. (There are a few other things you might have meant, but those are the most likely.)
For a simple definition of A, it is equivalent to:
A a(*new(A));
An A is dynamically allocated on the heap, a is copy constructed on the stack, and the dynamic allocation is leaked.
For a trivial definition of A the overall effect might as well be:
new A;
A a;
this copy implements the leak without the wasteful copy operation or the messy, redundant cast :)
I have a few silly questions (probably for most), it's less about 'how' do I do them and more about 'why' do they work this way? I know you are not supposed to ask multiple questions, but these are fairly small and related to one topic. Seems like it'd be a waste to separate them out.
I understand for the most part pointers, and the operators themselves. (Although I am curious why the * is called the de-reference operator, since isn't it referring to a reference of what it contains?)
I.e:
int x = 25;
int *p = &x;
So & makes sense, since *p is a place in the stack of type int that contains the address of x (which we know is 25).
So by saying *p are we 'referencing' the address of p which is pointing to the 25. Maybe it's just an English semantics thing? Maybe someone can explain why it's called 'de-reference'?
Take this valid code sample:
int *p = new int;
*p = 5
Simple enough, we're making a new place in the stack with the size of an int pointer (whatever that may be). p will contain some address that has a 5 for a value.
Thing is, I haven't actually declared anything that's storing a 5, so what the heck is p pointing to? I mean, this does indeed work, but I never made a int x = 5 or anything like that, and gave the address to p to point to? How does it even know?
p contains an address that points to something, but I never made that 'address' it's pointing to? Does the compiler just know to create another address somewhere else? (Sorry if this is a really stupid question.)
I was reading on here about some memory leaks on another question:
A *object1 = new A();
pretending A is a class first of all. Someone was saying the object1 stores the value of A. Isn't that incorrect? Doesn't object1 store the address of what new A() created and is pointing to it?
Because delete object1 deletes the pointer, which points to the new A() (but from the other question delete object1 would indeed be the correct syntax. So does that leave the new A() hanging out there? Or does it get automatically deleted? (As you can tell I'm a bit confused.)
If delete object1 does indeed delete what the pointer is pointing to and not the pointer itself, doesn't this just leave a dangling pointer?
Here
int x = 25;
int *p = &x;
* is not the dereferencing operator. It's part of the type of p. It basically says that p is a pointer.
Here
int *p = new int;
*p = 5;
The key is new int. It dynamically creates an int and returns it's address, so p now points to that address. *p = 5 (btw, here * is the dereferencing operator) modifies the value -- of that dymanically allocated int -- to 5
Indeed object1 holds the address of the newly created A. Since we're here we should clarify this: A is a (user defined) type. So it makes no sense to say that A has a value. Objects of type A have value.
delete p doesn't delete a pointer. It does 2 things:
Destroys an object created by a new-expression
Deallocates storage previously allocated by a matching operator new
The pointer isn't actually changed, i.e. it still points to the same address. Only now that address isn't allocated, i.e. can't be dereferenced anymore.
You can further refer to this SO answer - Static, automatic and dynamic storage duration to further understand objects, pointers, new/delete.
1: I'm not sure what you're implying when you say "which we know is 25". The address of x is not 25, rather that is the value of x. You do not set the address of x in a statment like int x = 25
But to answer your question, p is a reference, which is to say its value is an address. Accessing the value stored at the address p requires the *p, which dereferences the pointer.
2: You have allocated memory for p; you executed a new. You have allocated 4 (or 8) bytes of memory for a new integer on the heap, so p is pointing to a newly allocated block of memory. Saying *p = 5; tells the compiler to set the value stored at that address to 5.
3: Your assumption is correct; object1 does not store the value of a new A, rather points to a block of memory equivalent in size to aninstance of an object of size A.
delete object1; Does not delete the pointer. The pointer is simply an integer on the stack, rather it gives back the allocated memory for that pointer back to the system. A as you knew it is deleted, but the pointer still exists, and using it at this point is undefined behavior. You are correct in assuming you have a dangling pointer now, that is why you should always set deleted pointers to NULL.
I cannot resolve the following issue by myself:
Suppose we are reusing a memory in a following way:
struct A
{
int a;
A(){ }
~A(){ }
};
struct B : A
{
int b;
B(){ }
~B(){ }
};
A *a = (A*) malloc(sizeof(A) + sizeof(B));
B *b = new (a) B; //Constructor of B is calling
The lifetime of object reffered to by a has ended before the constructor of B is starting to call or it has ended when the constructor of B has finished?
You try to use the placement new operator to initialize b. This operator does not call the destructor of class A first (a), but initializes a new one into the memory pointed to by a. This is problematic (as mentioned in the comment), because the sizeof(B) is greater than sizeof(A) and you allocated only sizeof(A) at the pointer a. So it is undefined behavior.
The lifetime of the object a formally does not end. You get something like:
class A { int a; };
void* p = malloc(sizeof(A));
A* a1 = new (p) A();
A* a2 = new (p) A();
I think, you will get something like double called destructor on the same memory, but that is something compiler-implementation specific. I don't think, that the standard does say anything about this.
As soon as you enter the constructor of B, a is not pointing to an object A any more.
The reason is that even before the first instruction of the constructor of an object the runtime already has done the VMT, base sub-objects and member initialization.
Also if the constructor of B doesn't terminate because of an exception the memory has already been used anyway and another object eventually present at the same memory address doesn't exist any more.
In other words just don't do that... in C++ objects are not just a pile of bytes and they have rights; for example the right of having their destructor called ;-)
The standard from the relevant section (3.8) says,
The lifetime of an object of type T ends when:
- if T is a class type with a non-trivial destructor (12.4), the destructor call starts, or
- the storage which the object occupies is reused or released.
I interpret to mean that the life time of the object pointed to by a ends when members of B are initialized. Until that happens, the storage is not reused.
The lifetime of a ends when you delete it and not before - since forcing two different objects to occupy the same space this way is itself undefined behaviour and definitely not recommended your compiler may or may not treat that memory as available for reuse and overwrite b.
If you need to have two objects occupying the same location, e.g.: Message Variants or you are trying to write your own debugger then you should use a union type.
The other reason that you are not recommended to do this sort of thing is that you will create a maintenance nightmare. e.g. later in your code you could have:
b.b = 3
while (a.a > 0) {
b.b--;
}
I am little bit curious about that why memory is not allocated to a class or structure when we create pointer type object ?
For example :-
class A
{
public:
void show()
{
cout<<" show function "<<endl;
}
};
int main()
{
A *a;
a->show();
return 0;
};
Because pointers and memory allocation are a priori completely unrelated. In fact, in modern C++ it’s downright bad to use pointers to point to manually allocated memory directly.
In most cases, pointers point to existing objects – that’s their purpose: to provide indirection. To reiterate: this is completely unrelated to memory allocation.
If you want to directly have an object you don’t need a pointer: just declare the object as-is (= by value):
A a;
a.show();
This code:
A *a;
a->show();
just declares a pointer of type A*. Pointer alone is nothing but a variable that holds an address of some memory in it, i.e. it just points somewhere, nothing else. Pointer of type A* means that it points to memory, where an instance of type A is expected to be found.
a->show(); then just relies on this "expectation", but in fact it just uses uninitialized pointer, which results in undefined behavior.
This could be either solved by dynamically creating an instance of A:
A *a = new A();
a->show();
(which however gives you unpleasant responsibility for cleaning up this memory by calling delete a;) or even better: using an object with automatic storage duration instead:
A a;
a.show();
In the second case, an instance of type A is created automatically and its lifetime is tied to the scope, in which it has been created. Once the execution leaves this scope, a is destructed and memory is freed. All of that is taken care of, without you worrying about it at all.
Allocating a pointer does not equate to allocating an object. You need to use new and instantiate an object on the heap, or create the object on the stack:
A* a = new A();
// Or
A a;
A* aPntr = &a;
Pointer is not an object, it’s just a link that points somewhere. The reason to use them is that you can dynamically change what they’re pointing to.
A a;
A b;
A *pA;
{
bool condition;
// set condition here according to user input, a file or anything else...
if(condition)
pA = &a;
else
pA = &b;
}
Now I don’t have to take care about condition, it even doesn’t have to exist anymore and still I can profit from the choice made above.
pA->show();
Or I can use pointer to iterate over an array:
A array[10];
for(A* pA = array; pA < array+10; pA++)
{
pA->show();
}
(Note I used the original declaration of class A in both examples altough more meaningful it would be if each object of class A contained its specific information.)
There may not be one single reason for A *a; not to allocate an instance of A. It would be at odds with how C++ is designed. I would be somewhat surprised if Stroustrup considered it for long enough to identify a definitive reason not to do it.
A few different ways to look at it:
You didn't ask for an object of type A, so you don't get one. That's how C and C++ work.
A pointer object is an object that holds an address. You may as well ask why stationary manufacturers don't build a house when they manufacture an envelope, as ask why C++ doesn't allocate an object to be pointed at when you define a pointer.
There are many ways to allocate memory. Supposing that memory was going to be allocated, which one would you like? You could argue that in C++ new would be a sensible default for class types, but then it would probably be quite confusing either if char *c; called new char (because the behavior would be different from C) or if char *c; didn't allocate memory at all (because the behavior would be different from char *A;.
How and when would the memory be freed? If it's allocated with new then someone is going to have to call delete. It's much easier to keep things straight if each delete corresponds to a new, rather than each delete corresponding either to new or to defining a pointer with implicit memory allocation.
A pointer can be the location of an object, but it isn't always (sometimes it's null, sometimes it's off-the-end of an array). The object can be dynamically allocated but doesn't have to be. It would be very unhelpful of the language to make a pointer point to an object in cases where you don't need it. Therefore the language gives you the option not to allocate memory when defining a pointer. If you don't want that, then you should initialize the pointer with the result of a call to the memory-allocation mechanism of your choice.
You just create a pointer *a, but not allocate memory for it.
you should use A *a = new A();
Alright so I've been getting deeply into C++ as of late and I'm getting everything down. Pointers are finally starting to make sense as far as when I should use them, how to implement them correctly, etc.
However, there was one little question about the fundamental use of pointers that I still had that needed answered. I'll jump right to the code:
With the following class A and function foo(A* bar)...
class A
{}
void foo(A* bar)
{}
... what's the difference between the following calls to foo?
A* a;
A b;
foo(a);
foo(&b);
They both compile fine, and as far as I can remember I haven't had any issues with them.
I think that A b; is instantiated right there, whereas A* a; needs to be created with new (since it hasn't actually created the object, it's just held a 4-byte long reference to a potential A object).
I could, if I am thinking about this correctly, do a = b; (EDIT make that a = &b) and then successfully pass a to foo. But, if I don't do a = &b and foo tries to read the (non-existent) object pointed to by a, it will causes runtime errors.
Also, if the above is correct, then it's assumed I can successfully call foo(&b); just fine.
Am I correct?
Thanks!
Yes, Your understanding is correct.
foo(&b);
passes address of an already existing object of type A as an parameter to function foo().
foo(a);
passes a pointer to the type A as function parameter. To be able to do anything meaningful it must point to a valid A object.It can be done in two ways:
Allocating object on stack:
Create an object of the type A on stack(local storage) & make the pointer a point to this object:
A* a;
A b;
a = &b;
Dynamic Memory allocation:
A *a = new A;
Though, Once you do a dynamic memory allocation you will have to remember to free the alloated memory explicitly after use, or you will have a memory leak:
delete a;
Note that it is always better to avoid dynamic allocations as far as possible, and if you must do so, use Smart pointers instead of raw pointers.
You can't do a = b.
It would have to be a = &b, to set a to the address of b.
You are also correct about the memory management: b is allocated on the stack, while a allocates space only for a pointer and leaves creating the actual object to you.
foo(&b) will work file, where the behavior of foo(a) would be undefined before you initialize *a (such as via a = new A()).
In C++, pointers are first-class objects. A pointer isn't just an invisible reference that needs an associated object to have an identity. That's how Java/C# references work (or most other languages, really), but a pointer is an object in itself.
So A* a declares a pointer. It doesn't point to anything, and it doesn't have to point to anything. And if/when it points to something, it doesn't need to own that something.
So you don't need to do a = new A(). You can do a = &b as well (to have a contain the address of the object b. Or it can point to any other object of type A as well. A pointer is just an object that stores an address. It's key to your understanding that you throw away the notion that it "has an object" which "needs to be created".
It is an object, which contains an address (or it contains the special value null), and if it contains an address, there may or may not be an object of type A at that address.
You are mostly correct. You should not assume that pointers are 4 bytes (for example, it might be 8 on amd64 systems). Also, your assignment should be a = &b; (note the addition of the address operator). Other than that, it sounds pretty reasonable.