I have a question regarding the code snippet below:
double d = 20.1;
double* pd = new double;
...
pd = &d;
delete pd;
The last line throws an error in Visual C++ 2015. Does this mean that the pointer "pd" points to the stack address of "d" and its original pointed-to address in the heap (right-hand side of the equal sign in the second line) has leaked?
Yes, you leaked the double originally pointer by pd, but that's not what's causing the error.
The error is a result of you trying to delete a stack allocated address. That is is strictly undefined behavior. delete will only work for pointers which were created with new.
Variables hold values. Pointer values are just that, values. Not names. Not variables.
When you manipulate a pointer value, for example to pass it to delete, you only care about the value.
It's essentially equivalent to:
int one=1;
one=2;
std::cout << one; // you won't be surprised to see 2, will you?
The value currently in the variable matters; not some previous value. Not the name.
Your program tries to deallocate (delete) an object that wasn't allocated by you (the user), but by the compiler.
Does this mean that the pointer "pd" points to the stack address of "d" and its original pointed-to address in the heap (right-hand side of the equal sign in the second line) has leaked?
Yes, that is exactly what this means.
Related
I have a difficulties understanding pointers and how/when they fail. So I made a tiny program which creates a pointer, assigns a value to it and then prints that value. Compiles fine with both gcc and clang and does not give any warnings when using the -Wall switch. Why does it segfault and why does it not segfault when I assign a different value to the pointer first? I thought I had initialized the pointer to somewhere. When I just declare the pointer without initialization, then I rightfully get a compiler warning. However, here I do not get a compiler warning, but it still segfaults.
#include<iostream>
int main(){
int *b = (int*) 12; //pointer gets initialized, so it points to somewhere
//int a = 13; //works fine when uncommenting this and the next line
//b = &a;
*b = 11;
std::cout << "*b = " << *b << "\n";
return 0;
}
A pointer is a variable that save a memory address.
You "can" have any memory address in your pointer, but trying to read from memory space outside of where your application are allowed to read, will trigger the OS to kill you application with a segfault error.
If you allow me the metaphor:
You can write on a paper the address of any person in your country. But if you try to enter that house without permission, you most probably will get stopped by the police.
Back to code:
int *b = (int*) 123; // ok, you can save what you want.
std::cout << *b << std::endl; // SEGFAULT: you are not allowed to read at 123.
When you uncomment the two lines of code:
int a = 13;
b = &a;
Basically, b is not any-more pointing to that forbidden 123 address, but to the address of a. a is in your own code, and it memory is not forbidden to you, so accessing *b after this is allowed.
Reading at any hard-coded address is not forbidden by C++ (in fact it is useful in some situations), but your OS may not allow you to mess with that memory.
On the other hand, the compiler is able to detect a variable being used without initialization, and can warn this case. This has nothing to do with raw pointers.
A pointer is a variable to store an address.
int *b = (int*) 12;
This declares b as a pointer to a value of type int, and initializes it with the address 12. Do you know what resides at address 12? No, you don't. Thus, you should not use that address.
*b = 11;
This stores an integer 11 at the address pointed to by the pointer b. However, since pointer b points at address 12, the integer 11 overwrites something at that address (we don't even know what does it overwrite, because we don't know what is there to begin with). This could corrupt heap or stack or program's code or just cause an access violation, anything can happen.
But if you first do this:
b = &a;
Then pointer b now points at the address at which the variable a is stored. Thus, subsequently writing 11 at that address will just overwrite a's value (from 13 to 11), a perfectly valid operation, no problems.
I just need it to point to some location that can hold an int
Indeed, but this is not enough. Not only shall the location be able to hold an int, that location must also be available for your program to store such an int. This means the location needs to be either that of an existing object (e.g., of an existing variable of type int) or a newly allocated memory chunk capable of holding an int. For example:
b = new int;
This will dynamically allocate the memory needed to store an int, and assign the address of the newly allocated memory to the pointer b.
Remember that after you're done with such dynamically allocated memory, you should deallocate it:
delete b;
Otherwise, there will be a memory leak (at least until the whole process exits anyway).
Nowadays, in modern C++, there is rarely a need to use raw pointers to manage dynamic memory allocations/deallocations manually. You'd use standard containers and/or smart pointers for that purpose instead.
I wanted to ask, is dynamically creating a pointer, and then changing a pointer address to something else still deleting the original allocated space?
for example:
int main()
{
int c = 50;
// Memory leak
int * q = new int;
q = & c;
delete q;
}
What exactly is getting deleted or happening?
Thanks!
What exactly is getting deleted or happening?
Memory leaking and undefined behaviour.
When you do q = & c; you are losing your only tracking of the memory allocated by new int. Noone keeps track of this for you, there is no garbage collector, it is simply lost and cannot be recovered.
When you then do delete q; (where q is assigned to &c) you are deleting memory that you didn't allocate, and worse you are deleting memory on the stack. Either of these will result in undefined behavior.
This is an excellent preface into why you should avoid using pointers in circumstances where you don't need them. In this case, there is no reason dynamically allocate your int. If you really need a pointer, use a c++11 smart pointer (or boost if you don't have c++11). There are increasingly rare cases where you really do need a raw c type pointer. You should read Effective Modern c++ Chapter 4 for excellent detail on this subject.
is dynamically creating a pointer, and then changing a pointer address to something else still deleting the original allocated space?
No. delete will deallocate the memory to which its operand points. You must delete the same block of memory that you obtained from new.
int c = 50;
int * q = new int;
int * r = q;
q = & c;
delete q; // WRONG! q points to something you didn't get from new
delete r; // OK! p points to the block you got from new
To be even more clear, delete doesn't care about what variable it operates on, it only cares about what that variable points to. In the last line above, r points to the block that was originally pointed to by q and allocated by new, so you can safely delete it. q points to statically allocated memory, not something you got from new, so you can't delete it.
Instead of changing where q points, though, you can copy the value you want into the space that q points to:
int c = 50;
int * q = new int;
*q = c;
delete q; // OK! q still points to the same place
Here you're changing the value stored in the location to which q points, but you're not changing q itself. q still points to the block you got from new, so it's safe to delete it.
You code will (try to) delete c. There's no memory management or anything like that in C/C++. delete will try to delete whatever the given pointer points to, and and whatever is not deleted (either by calling delete for variables created with a call to new, or by leaving the scope for local variables) will remain in memory until the program ends.
Notice that trying to delete a local variable will propably cause a crash, since delete actually checks (in a very basic manner) what it deletes - at least to know how much memory has actually been allocated at that address. And at this check, it will propably notice that c doesn't include this information, or that it isn't even at the right end of the memory space, so it will crash.
It will crash because c is created in the stack memory section. If you're lucky and the program didn't crash you aren still leaking memory because the q reference is lost.
First answer is to your question:-
I wanted to ask, is dynamically creating a pointer
We don't create a pointer dynamically. Pointers are just a variable like other variable in C and C++. Difference is, pointer is a variable which can store the address of a particular memory location. In run time you just dynamically allocate memory and assign the address of first address location of that memory size into it.
Now what will happen if you don't delete/free the memory and assign a new address to it. In that case memory will not be release/freed and that can not be use anymore as that will never be marked as free by OS. When you free/delete memory O/S mark that area as free to use, and your running process can utilize it in future. That is call proper memory management. Improper memory manage leads your program to memory leak.
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.
Why can I do:
int i = *(new int (5));
and successfuly use i after it,
but when I'm trying:
delete &i;
I get a run time error:
Unhandled exception at 0x5ddccaf7 (msvcr100d.dll) in Test.exe:
0xC00000FD: Stack overflow.
If i was a reference:
int & i = *(new int (5));
, all this (including delete) works fine.
I know, that it's no good to keep allocated memory handler in something other than pointer and *(new ...) is awful, but I'm just wondering, why new works good, but delete fails.
//Below are just my guesses about the reason of such behavior:
Is it because module which executes program (it's probably not "compiler", because of there is run time already) when it encounters with delete, it searches for some information like length of data pointing by &i (in some internal array of such information about all pointers) and don't find it or interpretes some trash data as this information? (I suppose, pointers and references have it, but variables don't)
Your original version does not assign i to an address. It allocates a new int on the heap and initializes its value to 5, then copies that value into i which is on the stack. The memory that you allocated (new'ed) is inaccessible and gets leaked.
The reference version works because i refers to the otherwise-anonymous new'ed memory. Hence &i gives the heap address. In your first version, &i gives the address of the stack variable, not the heap memory, and deleting stack memory is bad news.
You get a run-time error because the address of i is not the same as the address returned by the operator new. Once you dereference the result of new, you make a copy of the value. That copy is then placed into variable i, which has an address in automatic storage, which cannot be passed to delete legally without triggering undefined behavior.
When you make a reference, however, you do not make a copy: the result of new becomes referenced through a variable i of type "reference to int". Hence, the reference has the same address as has been returned by operator new, so the code that uses the reference works fine.
The line:
int i = *(new int (5));
Is equivalent to:
int* p = new int(5);
int i = *p;
The address of i (which you are trying to delete) is not the address of the allocated memory.
In mathematical notation, &x == &y implies x == y, but x == ydoes not imply &x == &y.
int main()
{
char* a=new char[20];
cin>>a;
cout<<" character at 7-th position."<<a[6];
delete a+4;
cout<<a[0];
return 0;
}
Input:
1234567894567
Output:
character at 7-th position.6
*** glibc detected *** ./test free() invalid pointer:....
Now I have 3 questions
Is it correct that delete a+4 will only delete the character at a+4?
If answer to previous one is yes then what happens to a[0].We should get the output.
to delete a chunk of memory we should write delete[].But in this case how come all the elements are deleted?
There are only three types of pointer values you can pass as the operand of delete:
Null pointer values. They simply get ignored.
A complete scalar (not array) object previously allocated with new, either of:
The exact pointer returned by new
A pointer to a base subobject of the pointer returned by new, if and only if the base subobject's type has a virtual destructor
Any these pointer values should NEVER ever be passed to scalar delete:
The result of array new or new[] (use delete[] instead)
The result of malloc or any other allocator which is not new
The address of an object with automatic or static storage duration
The address of a member subobject or array element
Uninitialized pointer values
Pointers to already-deleted objects
If you break this rule, you get undefined behavior. That means your program might crash with a nice message that an invalid delete was detected. Or your data might get corrupted, saved in your data files, sent to your boss, shown to the customer, and later you get fired. So don't break the rule.
Your code falls into category "NEVER DO THIS #4".
The reason it works this way is because an implementation can (and most do) track extra information called metadata along with each allocated block. For example, the size of the block, which is pretty important for enabling reuse. There is no metadata for part of a block, and there may not be any way to find the metadata from a pointer into the middle.
No. delete is the opposite of new. You essentially delete the same pointer that you get when allocating. Deleting other pointers is undefined, hence your "invalid pointer" error. If you allocated an array, you have to use delete[]. Right now, you are leaking ("not freeing") that memory. So use delete [] a; after you are done.
Not really applicable.
Because that is how C++ works. It is the operation you use to free an array you allocated.
It appears that you want to remove a character from a string, then print the string. If that is what you are after, consider using a std::string and using its remove member function. Regardless, a[0] is a char, not a char*, the latter of which is a C style string. You should
cout << a;
instead.