delete[] and delete seems to behave alike - c++

here if I use delete or delete[] the output is still 70. Can I know why?
#include<iostream>
using namespace std;
int main()
{
int* c = new int[100];
for(int i=0; i<98; i++)
{
c[i] = i;
}
cout<<c[70]<<endl;
delete[] c;
or
delete c;
cout<<c[70]<<endl; //outputs 70 even after delete[] or delete
return 0;
}

Accessing deleted memory is undefined behavior. Deleting with the wrong delete is also UB. Any further discussion is pointless in the sense that you cannot reliably expect any outcome.
In many cases, UB will just do the "correct" thing, but you need to be aware that this is completely "by chance" and could change with another compiler, another version of the same compiler, the weather... To get correct code, you need to avoid all cases of UB, even those that seemingly work.

Using new will just allocate some memory to your program and return a pointer pointing at the said memory address, reserving as much memory as needed for the datatype. When you use delete later, it "frees" the memory, but doesn't delete it's content. If you had an int with the value 70 stored at that address, it will still contain 70, until another application wants some memory, gets said address and puts another value in there.
If you use new to allocate memory for an array, you will reserve following blocks of memory until there are enough blocks for your specified array length.
Let's say you do the following:
int main() {
int* array = new int[10]; // array now points to the first block of the allocated memory
delete array; // since array points to the first block of the array, it will only free that block, but nothing else, causing a memory leak
delete[] array; // will free all memory allocated by the previous new
// Note that you should never free allocated memory twice, like in this code sample. Using delete on already freed memory is undefined behaviour!
]
Always use delete for single variables and delete[] for arrays.
A demonstration of your problem:
int main() {
int* c = new int[10]; // We allocate memory for an array of 10 ints
c[0] = 1; // We set the value of the first int inside the array to 1
delete[] c;
/*
* We free the previously allocated memory.
* Note that this does not delete the CONTENT of the memory!
* c does still point towards the first block of the array!
*/
std::cout << c[0];
/*
* Firstly, this is undefined behaviour (Accessing deallocated memory).
* However, this will output 1,
* unless some other process allocated the memory at the address
* and filled it with another value already. (Very unlikely)
*/
return 0;
}
If you want to delete / overwrite the content of the deleted memory, you can use std::memset.
Example:
#include <cstring>
int main() {
std::size_t length = 10;
int* c = new int[length];
c[0] = 1;
std::cout << c[0] << std::endl; // Will output 1
std::memset( c, 0, length ); // Fill the memory with 0 bytes
delete[] c; // Now we free the array's memory
std::cout << c[0] << std::endl; // Will output 0
}

As others pointed its undefined behaviour and anything can happen.
These can be easily caught with the help of tools like valgrind.

Related

c++ delete pointer and then access the value of it points to

I just learned pointer and delete pointer in class for C++. I tried this code by my own
# include<iostream>
using namespace std;
int main(){
int num = 10;
int *p = new int;
p = &num;
cout << *p << endl;
delete p;
cout << num << endl;
return 0;
}
After deleting the pointer p, I cannot print the value of num. But if I delete p at the very end of the program, cout << num << endl; will give me 10. Anyone knows where I did run?
You first leaked a pointer
int *p = new int;
p = &num; // You just leaked the above int
then illegally deleted something you did not new
delete p; // p points to num, which you did not new
You have already received a couple of good answers that point out the mistake, but I read a deeper misunderstanding of the allocation and deallocation of heap vs stack variables.
I realised this has become a pretty long post, so maybe if people think it is useful I should put it as a community Wiki somewhere. Hopefully it clarifies some of your confusion though.
Stack
The stack is a limited and fixed size storage. Local variables will be created here if you don't specify otherwise, and they will be automatically cleaned up when they are no longer needed. That means you don't have to explicitly allocate them - they will start existing the moment you declare them. Also you don't have to deallocate them - they will die when they fall out of scope, loosely speaking: when you reach the end brace of the block they are defined in.
int main() {
int a; // variable a is born here
a = 3;
a++;
} // a goes out of scope and is destroyed here
Pointers
A pointer is just a variable, but instead of an int which holds a whole number or a bool which holds a true/false value or a double which holds a floating point, a pointer holds a memory address. You can request the address of a stack variable using the address operator &:
{
int a = 3, b = 4;
int* p = &a; // p's value is the address of b, e.g. 0x89f2ec42
p = &b; // p now holds the address of b, e.g. 0x137f3ed0.
p++; // p now points one address space further, e.g. 0x137f3ed4
cout << p; // Prints 0x137f3ed4
} // Variables a, b and p go out of scope and die
Note that you should not assume that a and b are "next to" each other in memory, or that if p has a "used" address as its value then you can also read and write to the address at p + 1.
As you probably know, you can access the value at the address by using the pointer indirection operator, e.g.
int* p = &a; // Assume similar as above
*p = 8;
cout << a; // prints 8
cout << &a << p; // prints the address of a twice.
Note that even though I am using a pointer to point at another variable, I don't need to clean up anything: p is just another name for a, in a sense, and since both p and what it points to are cleaned up automatically there is nothing for me to do here.
Heap
The heap memory is a different kind of memory, which is in theory unlimited in size. You can create variables here, but you need to tell C++ explicitly that you want to do so. The way to do this is by calling the new operator, e.g. new int will create an integer on the heap and return the address. The only way you can do something sensible with the allocated memory, is save the address this gives you. The way you do this, is store it in a pointer:
int* heapPtr = new int;
and now you can use the pointer to access the memory:
*heapPtr = 3;
cout << heapPtr; // Will print the address of the allocated integer
cout << *heapPtr; // Will print the value at the address, i.e. 3
The thing is that variables created on the heap will keep on living, until you say you don't need them anymore. You do that by calling delete on the address you want to delete. E.g. if new gave you 0x12345678 that memory will be yours until you call delete 0x12345678. So before you exit your scope, you need to call
delete heapPtr;
and you will tell your system that the address 0x12345678 is available again for the next code that comes along and needs space on the heap.
Leaking memory
Now there is a danger here, and that is, that you may lose the handle. For example, consider the following:
void f() {
int* p = new int;
}
int main() {
f();
cout << "Uh oh...";
}
The function f creates a new integer on the heap. However, the pointer p in which you store the address is a local variable which is destroyed as soon as f exits. Once you are back in the main function, you suddenly have no idea anymore where the integer you allocated was living, so you have no way to call delete on it anymore. This means that - at least for the duration of your program - you will have memory that according to your operating system is occupied, so you cannot use it for anything else. If you do this too often, you may run out of memory even though you can't access any of it.
This is one of the errors you are making:
int* p = new int;
allocates a new integer on the heap and stores the address in p, but in the next line
p = &num;
you overwrite that with another address. At this point you lose track of the integer on the heap and you have created a memory leak.
Freeing memory
Aside from freeing memory not often enough (i.e. not instead of once), the other error you can make is freeing it too often. Or, to be more precise, you can make the error of accessing memory after you have told your OS you don't need it anymore. For example, consider the following:
int main() {
int* p = new int;
*p = 10;
delete p; // OK!
*p = 3; // Errr...
}
That last line is very wrong! You have just returned the memory allocated when you called delete, but the address is still stored in p. After you call delete, your OS is allowed to re-allocate the memory at any time - for example, immediately after another thread could call new double and get the same address. At that point, if you write *p = 3 you are therefore writing to memory that is no longer yours which may lead to disaster, if you happen to overwrite the location in memory where the nuke's launch codes are stored, or nothing may happen at all because the memory is never used for anything else before your program ends.
Always release your own memory, and nothing but your own memory
We have concluded the following: memory allocated on the stack is not yours to claim, and not yours to release. Memory allocated on the heap is yours to claim, but you must also release it once and only once.
The following examples are incorrect:
{
int a = 3;
int* p = &a;
delete a;
} // Uh oh... cannot clean up a because it is not ours anymore!
{
int* p = new int;
delete p;
*p = 3; // Uh oh, cannot touch this memory anymore!
delete p; // Uh oh, cannot touch this memory anymore!
}
Why does it print 10?
Well, to be honest, you were just "lucky" there. Actually, the way your operating system manages memory, is generally pretty lazy. When you tell it "I would like some memory" it doesn't zero it for you. That is why it is a bad idea to write
int main() {
int a;
a = a + 3;
cout << a;
}
You get allocated a variable a somewhere in the memory, but the value of a will be whatever was in that memory location. It might be zero, or some random number that depends on how the bits fell when you booted your computer. That is why you should always initialize the variable:
int a = 0;
Similarly, when you say "I don't need this memory" anymore, the OS doesn't zero it. That would be slow and unnecessary: all it needs to do is mark the memory as "free to be re-allocated". So if you give it back and access it immediately afterwards, the probability that it has not been re-allocated yet is pretty large. Therefore
int* p = new int;
*p = 10;
delete p;
cout << *p;
is not guaranteed to print 10. The address p is pointing to may have been (partially) taken (and initialized!) by someone else immediately after the delete. But if it hasn't, the memory will still contain the value 10 there so even though it isn't yours anymore, C++ will still allow you to access it. Basically, when you are using pointers, you are telling it "trust me, I'm a programmer - you don't need to do all kinds of slow checks to make sure I'm staying where I'm supposed to be, instead I'll be careful about that myself!"
using namespace std;
int main(){
int num = 10; // a) an int is created on stack
int *p = new int; // b) another int is allocated on heap
p = &num; // c) address of int from stack is assigned to p and the pointer
// allocated in b) is leaked: as nothing points to it anymore,
// it can't be deleted
cout << *p << endl;
delete p; // d) deleting a pointer that was not dynamically allocated
// and is pointing to stack.
cout << num << endl;
return 0;
}

Pointers and dynamically allocated arrays in C++

I'm trying to get this clear up in my mind.
int* arrayA = new int[3];
int arrayB[3] = {1,2,3}
arrayA = arrayB;
Does the value of arrayB get copied over to arrayA?
Or does arrayA become a pointer to arrayB?
Naked new is evil, especially for arrays. Use std::vector if you need dynamic array and std::array if you need static one.1
Now the actual answer is simple. arrayA is a pointer. So it's made to point to arrayB. That has additional effect that:
you now leaked the allocated pointer.
attempt to delete arrayA will now crash or something else unpleasant, because you would be trying to free unallocated memory.
Actually while C++ allows assigning structures and classes, it does not support assigning arrays at all. Unless part of an object either managed as in std::vector or as array member as in std::array (note: std::array is C++11).
1 The main reason is that the containers guarantee the resources will be released in their destructors, so called RAII idiom, avoiding most opportunities for memory leaks and dangling references.
int* arrayA = new int[3];
arrayA now stores the address in memory of a different memory block thats large enough to contain 3 ints which is stored on the heap.
int arrayB[3] = {1,2,3};
arrayB is a block of memory thats large enough to contain 3 ints which is stored on the stack.
arrayA = arrayB;
Copies the address of the memory block that's stored on the stack into the variable arrayA. You have now lost the only reference to memory block stored on the heap, and have no way to free up the memory (a memory leak)
The memory stored on the stack and now pointed to by arrayA will not be safe to access when the current function returns. In particular returning arrayA (or arrayB) is not safe.
For
Does the value of arrayB get copied over to arrayA?
Nope. It will not copy arrayB to arrayA. If you want to do so, you can do like,
for (int i=0;i<3;i++) arrayA[i]=arrayB[i]; //This is two arrays has same value
does arrayA become a pointer to arrayB?
Yes. It become a pointer to array of arrayB. After arrayA = arrayB; statement, memory allocated in the first line can not be accessible and it is a leak.
arrayA=arrayB; result in copying the address of arrayB to arrayA. arrayA will start pointing to the arrayB. Check it using,
printf("\n Base address of A[%u] base address of B[%u]", arrayA, arrayB);
Hope this helps.
Array name represents the base address of the array.
arrayA=arrayB;
stores the base address of arrayB to arrayA. The further values can be accessed by incrementing the pointer arrayA.
i.e
*(arrayA) value is 1
*(arrayA+1) value is 2
*(arrayA+2) value is 3
The memory created should be freed at the last using
delete[] arrayA
Q. Does the value of arrayB get copied over to arrayA?
Ans. NO
Or
Q. does arrayA become a pointer to arrayB?
Ans YES.
But the memory chunk which you allocated using new is lost. As no one is having the address which was starting point of that chunk.
This is vindicated by this program :
#include<iostream>
using namespace std;
const int MAX=4;
int main(){
int* arrayA = new int[MAX];
for(int i=0;i<MAX;i++){ arrayA[i]=i; }
int arrayB[MAX] = {10,20,30,40};
arrayA = arrayB;
for(int i=0; i<MAX;i++){ cout<<" a["<<i<<"] = "<<arrayA[i]<<endl; }
return 0;
}
The output of this code is :
a[0] = 10
a[1] = 20
a[2] = 30
a[3] = 40
on
g++ (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4
which is true in general as well.
visualization of this is somewhat like this
arrayA-> [0][1][2][3]
arrayB-> [10][20][30][40]
Intially arrayA has address of [0] ( + sum extra memory on the negative indexes for size used by compiler to do the de-alloctation ).
after
arrayA=arrayB;
arrayA has address of [10];
suppose you call delete on arrayA what shall happen ??
*** Error in `./a.out': double free or corruption (out): 0x00007fff561281d0 ***
This is evident from the following code also
#include<iostream>
using namespace std;
const int MAX=4;
int main(){
int* arrayA = new int[MAX*2];
for(int i=0;i<MAX;i++){ arrayA[i]=i; }
int* arrayC = new int[MAX];
int j=0;
for(int i=MAX*100;i>=0;i-=10,j++){ arrayC[j]=i; }
arrayA = arrayC;
for(int i=0; i<MAX;i++){ cout<<" a["<<i<<"] = "<<arrayA[i]<<endl; }
delete[] arrayA;
return 0;
}
The out put is :
a[0] = 400
a[1] = 390
a[2] = 380
a[3] = 370
*** Error in `./a.out': free(): invalid next size (fast): 0x0000000002028040 ***
Aborted (core dumped)
Just pay attention to :
"invalid next size"
This clearly says about the size value written before the arrayA in the negative indexes.

segmentation fault when free() is used

This code causes a Segmentation Fault:
int main(){
char *p;
char a[50] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
p = (char *)malloc(50*sizeof(char));
if(!p){
cout << "Allocation Failure";
cout << "\n";
}
else{
cout << "Allocation Success";
cout << "\n";
p = a;
cout << p;
cout << "\n";
free(p);
}
return 0;
}
The output after executing this program is:
Allocation Success
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Segmentation fault
I am not able to find the bug. What may be reason?
This:
p = a;
copies the pointer, not the contents of the pointed-to memory. p now points at the first element of the array a. So when you do free(p), you're trying to free a non-dynamic array, which doesn't make any sense.1
You should investigate strncpy() to copy strings.
1. And it also causes a memory leak.
You're calling free on a block of memory that wasn't allocated using one of the malloc methods.
When you do: p = a you're assigning to p the memory used by the stack array a. That memory wasn't allocated using malloc and hence it can't be freed using free.
Furthermore with that re-assignment, you'll lose track of the block that you originally allocated with malloc and assigned to p, causing a memory leak.
char a[50] allocates an array of fifty characters on the stack. a therefore points at an address on the stack.
p = a sets p to point at the same address as a. Therefore after p = a, p points at an address on the stack. Remember, p contains an address.
Afterwards, free(p) tries to free a region of memory on the stack, which is illegal. You can only free memory you got from malloc().
you actually meant memcpy(p,a,50); not p=a, remember C does not have a string data type.
p = a; // p points a
Executing this line, p should be pointing to const string (char *).
You cannot free() anything that is not obtained by calling malloc or calloc. Since in this example you try to free() a const string, you get an error.

Deleting a dynamically allocated jagged array

I have an array of pointers that point to arrays of ints.
I have made a hard coded array of ints (check 'array' below) and I want to insert it into the array of pointers (check 'bar' below), as far as I can tell, it is still an array of pointers that point to arrays of ints.
It compiles fine; no warnings.
It runs fine; and closes fine;
Until at least, I introduce the currently commented out delete statement in the destructor.
I imagine my compiler would make a better destructor at this point, but I'm interested as to what I'm doing wrong. The terminal window just throws out a gigantic memory map; and googling and searching SO didn't help much.
class foo {
public:
int **bar;
int aSize;
//CONSTRUCTOR
foo(int aSize) {
this->aSize = aSize;
bar = new int*[aSize];
for (int i=0;i<aSize;i++) {
bar[i] = new int[aSize + i];
for (int j=0;j<(aSize + i);j++) {
bar[i][j] = 0;
}
}
}
void myfunc(int *pointer) {
bar[0] = pointer;
}
~foo() {
for (int i=0;i<aSize;i++) {
//delete[] bar[i];
}
delete[] bar;
}
};
int main() {
foo *obj = new foo(5);
int array[] = {1,2,3,4};
obj->myfunc(array);
delete obj;
return 0;
};
I know I've probably done something tragic; I just don't know what it is yet.
There is a reason why I am not using STL or other templates, it is simply because I'm interested in learning this.
Maximum criticism appreciated.
The myfunc function takes in a pointer, and then sets bar[0] to that memory address. In your example code, you pass it the address of array, which is an automatic (stack) variable. The destructor then attempts to delete[] bar[0], which points to a stack variable. This is completely undefined behavior, and the reason your program is crashing. You can't delete[] a stack array. You can only delete[] an array which was allocated using new[].
Also, the myfunc function is always going to leak memory, because bar[0] points to a heap-allocated array. When you set bar to a different memory address without first delete[]ing the previous address, you are leaking memory.
The problem is calling myfunc. In that function, you are replacing a pointer (bar[0]) that your class thinks it owns. Your obj destructor will then consequently try to run delete[] on your array[] in main, which probably causes your crash and leaves your original bar[0] dangling.

Freeing memory allocated to an array of void pointers

I am declaring an array of void pointers. Each of which points to a value of arbitary type.
void **values; // Array of void pointers to each value of arbitary type
Initializing values as follows:
values = (void**)calloc(3,sizeof(void*));
//can initialize values as: values = new void* [3];
int ival = 1;
float fval = 2.0;
char* str = "word";
values[0] = (void*)new int(ival);
values[1] = (void*)new float(fval);
values[2] = (void*)str;
//Trying to Clear the memory allocated
free(*values);
//Error: *** glibc detected *** simpleSQL: free(): invalid pointer: 0x080611b4
//Core dumped
delete[] values*;
//warning: deleting 'void*' is undefined
//Similar Error.
Now how do I free/delete the memory allocated for values ( the array of void pointers)?
I suspect the issue is with the way that you allocated values: values = (void*)calloc(3,sizeof(void)). That should be sizeof(void *) rather than just sizeof(void).
sizeof(void) may be zero or something else that makes no sense, so you're not really allocating any memory to begin with... it's just dumb luck that the assignments work, and then the error pops up when you try to deallocate the memory.
EDIT: You're also asking for trouble by alternating between C++-style new/delete with C-style malloc/free. It is okay to use them both as long as you don't delete something you malloc'ed or free something you new'ed, but you're going to mix them up in your head if you go like this.
You have 3 things that are dynamically allocated that need to be freed in 2 different ways:
delete reinterpret_cast<int*>( values[0]);
delete reinterpret_cast<float*>( values[1]);
free( values); // I'm not sure why this would have failed in your example,
// but it would have leaked the 2 items that you allocated
// with new
Note that since str is not dynamically allocated it should not (actually cannot) be freed.
A couple of notes:
I'm assuming that the sizeof(void)
was meant to be sizeof(void*)
since what you have won't compile
I'm not going to say anything about
your seemingly random casting except
that it looks like code that ready
for disaster in general
This is the perfect situation for the boost::any class
Also you may want to consider using a vector rather than allocating your own memory.
std::vector<boost::any> data;
boost::any i1 = 1; // add integer
data.push_back(i1);
boost::any f1 = 1.0; // add double
data.push_back(f1);
data.push_back("PLOP"); // add a char *
std:: cout << boost::any_cast<int>(data[0]) + boost::any_cast<double>(data[1])
<< std::endl;
Going back to your original code the main problem was:
values = (void*)calloc(3,sizeof(void));
// This should have been
void** values = (void**)calloc(3,sizeof(void*));
// Freeing the members needs care as you need to cast them
// back to the correct type before you release the memory.
// now you can free the array with
free(values);
Also note: Though it is not illegal to use both new/delete and calloc/free in the same piece of code it is frowned upon. Mainly because it is easy to get things mixed up and that could potentially be fatal.
You're mixing new and *alloc(). That's a no-no, and can lead to undefined results.
I'm not sure why you are using new if you're doing things in C (referencing the tag here).
I would malloc the individual pieces of the array I need and then free them when I'm done I suppose. You can't free something you didn't first malloc. You also can't delete a void pointer.
Note that you're also not deleting values[0] and values[1] which is a memory leak, Yet by your design you can't free values[2] since its a pointer into you .data section.
You'd have to keep track of how many void* were originally calloc'd, and iterate over them, free-ing each one, then free the original values variable.
darn formatting... (the preview is working fine).
int ct = 3;
values = (void*)calloc(ct,sizeof(void));
//can initialize values as: values = new void* [3];
int ival = 1;
float fval = 2.0;
char* str = "word";
values[0] = (void*)new int(ival);
values[1] = (void*)new float(fval);
values[2] = (void*)str;
for ( int i = 0; i < ct; i++ ) [
delete( values[i] );
}
free( values );