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.
Related
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.
For example:
int *a, *b;
a = new int[10];
b = new int(12);
b = a; // I know there's memory leak, but let's ignore it first
delete [] b; // line L
What will happen? Will the entire array be deleted successfully?
What if line L is replaced by this:
b = a + 1;
delete [] b;
Or by this:
a++;
delete [] a;
And, lastly, if the length of an dynamic array is associated with the starting address, or in other words, associated with the array itself, do we have any way to get the length of it without using another variable to store the length?
Thanks a lot!
The memory block size and array length information is associated with the address of the object, which is the address of the first item of the array.
I.e. your delete[] is safe in the given code
int *a, *b;
a = new int[10];
b = new int(12);
b = a; // I know there's memory leak, but let's ignore it first
delete [] b; // line L
However, there is no portable way to 1access the associated information. It's an implementation detail. Use a std::vector if you need such info.
To understand why the info can't be accessed, note first that memory block size, needed for deallocation, can be larger than the array length times size of array item. So we're dealing here with two separate values. And for an array of POD item type, where item destructor calls are not necessary, there needs not be an explicitly stored array length value.
Even for an array where destructor calls are necessary, there needs not be an explicitly stored array length value associated with array. For example, in code of the pattern p = new int[n]; whatever(); delete[] p;, the compiler can in principle choose to put the array length in some unrelated place where it can easily be accessed by the code generated for the delete expression. E.g. it could be put in a processor register.
Depending on how smart the compiler is, there needs not necessarily be an explicitly stored memory block size either. For example, the compiler can note that in some function f, three arrays a, b and c are allocated, with their sizes known at the first allocation, and all three deallocated at the end. So the compiler can replace the three allocations with a single one, and ditto replace the three deallocations with a single one (this optimization is explicitly permitted by 2C++14 §5.3.4/10).
1 Except, in C++14 and later, in a deallocation function, which is a bit late.
2 C++14 §5.3.4/10: “An implementation is allowed to omit a call to a replaceable global allocation function (18.6.1.1, 18.6.1.2).
When it does so, the storage is instead provided by the implementation or provided by extending the
allocation of another new-expression. The implementation may extend the allocation of a new-expression e1
to provide storage for a new-expression e2 if …”
int *a, *b;
a = new int[10];
b = new int(12);
b = a; // I know there's memory leak, but let's ignore it first
delete [] b; // line L
Will the entire array be deleted successfully?
Yes, memory will successfully be freed since the pointer a was set to point to an array of 10 integers
a = new int[10];
then the same memory location address is stored into b
b = a;
therefore the delete[] line correctly deallocates the array chunk
delete [] b;
As you stated the code also leaks the integer variable 12 that was originally allocated and pointed to by b.
As a sidenote calling delete[] to free memory not associated with an array (specifically with a static type mismatch - see [expr.delete]/p3) would have triggered undefined behavior.
Now for some internals on where is the size information stored when allocating memory.
Compilers have some degree of freedom (cfr. §5.3.4/10) when it comes to memory allocation requests (e.g. they can "group" memory allocation requests).
When you call new without a supplied allocator, whether it will call malloc or not, it is implementation defined
[new.delete.single]
Executes a loop: Within the loop, the function first attempts to allocate the requested storage.
Whether the attempt involves a call to the Standard C library function malloc is unspecified.
Assuming it calls malloc() (on recent Windows systems it calls the UCRT), attempting to allocate space means doing book-keeping with paged virtual memory, and that's what malloc usually does.
Your size information gets passed along together with other data on how to allocate the memory you requested.
C libraries like glibc take care of alignment, memory guards and allocation of a new page (if necessary) so this might end up in the kernel via a system call.
There is no "standard" way to get that info back from the address only since it's an implementation detail. As many have suggested, if you were to need such an info you could
store the size somewhere
use sizeof() with an array type
even better for C++: use a std::vector<>
That info is furthermore associated with a memory allocation, both of your secondary cases (i.e. substituting the L line with
b = a + 1; delete [] b;
or
a++; delete [] a;
will end in tears since those addresses aren't associated with a valid allocation.
The c++ standard just says that using delete[] on a pointer allocated with new, and using delete on a pointer allocated with new[] is undefined behavior.
So doing this may work, or may not, depending on implementations. It may set your house on fire.
For instance, just suppose that these functions are based on an underlying buffer using malloc() and free().
new and delete will, in most implementations, use a buffer which has exactly the size and address of the item (here an int)
new[] and delete[] are more complex. They must store in the buffer not only size items, but also the value of size. An implementation could store size before the actual items. This would mean that the pointer of the underlying buffer is not the same as the pointer to the first item, which is the value returned by new[]
Mixing array and non array versions would then call free() on invalid pointers, ie pointers that were never returned by malloc. This will crash or trigger an exception
Of course, all this is implementation defined.
I have a member function that I call, from there I get a pointer to a private member which is of class BankAccount, I am unsure what happens with the pointers when I deallocate them. I create a new pointer and heap memory address but then assign the pointer to something else. What does "delete" end up deleting?
I read that if you delete a pointer
Here is the code
void Employee::raise(){
BankAccount* tempBank = new BankAccount(); //set pointer to new heap place
double amt;
tempBank = get_bank(); // set pointer to existing heap implicitly
amt = tempBank->get_amount();
amt = (amt + (amt/12));
tempBank->set_amount(amt);
delete tempBank; //does this delete new heap created or does it add a new block of
//memory to heap since it is trying to delete a pointer assigned
//by memory address
tempBank = NULL;
}
I realized I could just do the code below to avoid this situation, but now I am curious as to what happens in the above situation with the memory
BankAccount* tempBank = get_bank();
So what exactly happens when delete is called in my original situation?
When you use delete ptr; the object pointed to by ptr is destroyed and the corresponding memory is returned to the memory management system. The variable ptr and any copy thereof hold a bit pattern referring to now inaccessible memory (the system may still allow you to actually access this memory and it may even still contain the original data but that's undefined behavior and you shall not rely on it).
Put differently, the memory deallocation does not affect the pointer but it does affected the pointed to entity. In your case, the BankAccount, i.e., the result of *tempBank gets destroyed while the pointer tempBank remains unchanged by the delete operation. Obviously, setting tempBank to NULL does change this specific pointer but none of the other copies (if any), giving you false sense of security: I'd not set deleted pointers to NULL unless I keep them around for whatever reason...
Pointers are essentially just the address of the first byte in memory that belongs to the data structure they point to. So in your case:
BankAccount* tempBank = new BankAccount(); // this creates a new object of type BankAccount
// the pointer tempBank points to the first byte of that object in memory
tempBank = get_bank(); // now tempBank points to the first byte of whatever is returned from get_bank()
// that means that you no longer know the address of the object you created above (tempBank now points to something different)
// C++ has no garbage collection, so you just leaked that memory
delete tempBank; // you delete the object that was returned from get_bank
// so that memory is now marked as free and can be reused by whatever needs it
tempBank = NULL; // this is good style, you should always do it, but it does nothing to any allocated memory
BTW: using plain new and delete and owning raw pointers is considered bad style in modern C++. YOu might want to consider using std::shared_ptr or std::unique_ptr (or their boost equivalents if you cannot use C++11 yet)
I found this information that may be useful to you:
ordinary delete Deallocates the memory block pointed by ptr (if not null), releasing the storage space previously allocated to it by a call to operator new and rendering that pointer location invalid.
You can find more information in the original url: http://www.cplusplus.com/reference/new/operator%20delete/
delete tempBank;
when delete is called on pointer , it releases memory pointed by that variable[tempBank].
There are two notions of delete in C++: One is the operator, declared as ::operator delete(void*), which basically only frees up the memory and isn't usually thought about by most programmers. The other is the delete expression, delete p;, where p is a T*. The expression invokes the destructor of the object pointed to by p (and then frees the memory), which is a crucial language feature of C++ that has no analogue in C.
Well first of all, you are allocating from heap with your first exp which is
BankAccount* tempBank = new BankAccount();
and you lose the address of it with assigning another object address to tempBank pointer by
tempBank = get_bank();
so actually when you delete tempBank; you actually deleting the object that you allocated in the function get_bank(). Also because you have lost the address of object that you allocated with new BankAccount(), there is no more way to delete it, because you do not know the address of this object.
In your question, Are you sure that get_bank() indeed returns pointer to object allocated on heap (and not address of just plain object on stack). You have not mentioned it clearly hence it's worth to confirm it again. Now, coming back to question, if get_bank() returned pointer to private member which let's say was not on heap - in that case doing doing tempBank will result in undefined behavior because you can only invoke delete on an object which was created using new. But if get_bank() returned pointer to object allocated on heap then it will free memory of that object and then accessing that object from any other member function could become a nightmare!
You can check below link for some more related information,
Calling delete on variable allocated on the stack
This looks simple question but my friend debated with me that below program invokes UB. But I think he is incorrect.
Consider following program:
#include <iostream>
int main()
{
int* p=new int[3]();
int* q=p;
for(int i=0;i<3;i++)
std::cout<<q[i]<<' ';
delete[] q;
std::cout<<'\n';
}
Is this program's behavior well defined? What happen if I write delete[] p; instead of delete[] q; ? Is it valid?
Yes the program is well defined. First you create a pointer assigned to newly allocated memory.
int* p=new int[3]();
Then you create another pointer pointing to that memory
int* q=p;
You then use that pointer to assign data into that memory. After that you delete memory which is pointer to q which is the same as p which is okay. The program returns and all is well
delete doesn't care about what variable you use. What is important is that the memory that the pointer points to was created with new and that you only call delete once on the memory.
The pointer returned by the new[] operator is not the start of the allocated memory but rather points to the first object (or the object at index 0). Now, based on the compiler you're using, the run-time system stores the number of objects, n, somewhere where it can be retrieved if you only know the memory location pointed by p.
According to this blog, the deletion of a vector performs this operation in reverse:
When you do "delete[] p", you are saying, "p points to a bunch of
objects, but I'm not telling you how many." In this case, the compiler
needs to generate extra code to keep track of how many it needs to
destruct. This extra information is kept in a "secret place" when the
vector is allocated with "new[]".
Since doing int *q = p essentially points to the same array's 0th object, it is equivalent to call delete[] q and delete[] p.
Operator delete can be applied ONLY to memory (i.e. address) that was allocated with operator new. If you allocate once you should free (detele) also once, does not metter which pointer (variable storing address) is used, so your code is valid.
But, remember, after you delete[] q neither q nor p DO NOT have to be used. The best way is assigne NULL to both pointers.
No UB. It will work fine. Not much to add here.
I have a class with a vector of pointers to objects. I've introduced some elements on this vector, and on my main file I've managed to print them and add others with no problems. Now I'm trying to remove an element from that vector and check to see if it's not NULL but it is not working.
I'm filling it with on class Test:
Other *a = new Other(1,1);
Other *b = new Other(2,2);
Other *c = new Other(3,3);
v->push_back(a);
v->push_back(b);
v->push_back(c);
And on my main file I have:
Test t;
(...)
Other *pointer = t.vect->at(0);
delete t.vect->at(0);
t.vect->erase(t.vect->begin());
if (pointer == NULL) { cout << "Nothing here.."; } // Never enters here..
Deleting a pointer doesn't have to zero it, it just frees the memory assigned there. Using pointer is undefined after the delete though, as the memory is free to be used for other things. Technically the C++ spec intentionally leaves it up to implementations whether they want to zero a deleted pointer or not, but practically none that I know of do so
The deletion of memory pointed by a pointer, doesn't set the pointer to NULL.
You set pointer equal to the address of something, and never touched it again, so of course it won't be null. The fact that you then did something to the object is irrelevant.
Using simple pointers, there is no safe way for pointer to determine whether the object it once pointed to has been deleted. The simplest way to do what you seem to want to do is by leaving it to the containers: if you're interested in that object, search for pointer in the vector to see whether it's still there (and don't delete the object without erasing the corresponding element from the vector, or you'll have the same problem all over again).
To overcome the checking a deleted ptr problem you could use boost::shared_ptr.
Instead of delete use .reset() and to check if the ptr is still valid use .get()
(Actually you can just use if(p) where p is the shared_ptr because it has a conversion to bool)