New and delete mix ups - c++

I have a small problem with using the new and delete operators. I read in a bunch of places that every new operator has to correspond to a delete, and as I understand it, variables created with new will persist until they are hit with that delete. If you would please look at the following code, it's longish but straightforward:
#include <iostream>
using namespace std;
int* testFunction1();
int* testFunction2();
int main(){
int* ptr1 = testFunction1();
int* ptr2 = testFunction2();
cout << *ptr1 << endl; // outputs 5
cout << *(ptr1 - 1) << endl; // outputs random int
cout << *ptr2 << endl; // outputs random int
cout << ptr1 << endl; //prints address of b from testFunction1()
cout << ptr1 - 1 << endl; // prints address of a and c from testFunction1()
cout << ptr2 << endl; // prints address of a and c from testFunction1()
cout << endl;
// delete ptr1; won't work
return 0;
}
int* testFunction1(){
int a = 5, b = 10;
int* pointerToInt1 = new int;
pointerToInt1 = &a;
pointerToInt1 = &b;
cout << &a << endl;
cout << &b << endl;
return pointerToInt1;
}
int* testFunction2(){
int c = 5;
int* pointerToInt2 = &c;
cout << &c << endl;
return pointerToInt2;
}
I have two questions:
I figured that, with testFunction1(), I am returning the pointer by value. But I don't know how to fix that, to return a reference to the pointer, so that I can free the memory in the main method (or for that matter, any other method).
Why did I get 5 as an output when I dereferenced *ptr1? I mean, from the address output, it's clear that the value assigned to c in testFunction2() was stored there, but why did that happen?

Let's don't put your questions aside and explain your code first.
You declare and defined a function named testFunction1 which returns int poitner
int* testFunction1(){
int a = 5, b = 10; // define local variables with initial values. a,b have different memory addresses
int* pointerToInt1 = new int; // dynamic allocate pointer(new address) to int
pointerToInt1 = &a; // set pointerToInt1 to point to address of a
pointerToInt1 = &b; // set pointerToInt1 to point to address of b
cout << &a << endl;
cout << &b << endl;
return pointerToInt1; // return pointerToInt1 pointer which currently points to address of b
}
a,b are local variables inside function testFunction1, they have automatic duration, when function finishes they are release, so pointerToInt1 actually is dangling pointer and access it is undefined behavior.
Also a typical memory leak is introduce in testFunction1, original memory block allocated by new is lost.
int* pointerToInt1 = new int;
pointerToInt1 = &a;
Now, let's "fix" function testFunction1, yup, I mean fix with double quotes.
int* testFunction1(){
int a = 5, b = 10;
int* pointerToInt1 = new int;
*pointerToInt1 = a; // copy a to memory pointerToInt1
*pointerToInt1 = b; // copy b to memory pointerToInt1
cout << &a << endl;
cout << &b << endl;
return pointerToInt1; // return pointerToInt1 pointer
}
After you call function testFunction1, you still need to delete the dynamically allocated memory block.
int *p = testFunction1();
delete p;
Now if you go back and review your two questions, do you get the answer?

You are setting the pointer to a variable allocated on stack:
int a = 5, b = 10;
int* pointerToInt1 = new int; // allocates an int on heap
pointerToInt1 = &a; // overwrite pointer with a local variable
What happens is that the pointer you return points to a value that has automatic allocation on stack so the pinter becomes invalid when the function exits its scope.
In addition, since you lose any reference to the object you allocated dynamically on heap, you can't delete it anymore so it's leaked memory.
Finally the delete tries to delete a pointer which points to an address that was on stack during the call to testFunction1 so it's not a valid pointer anymore, hence delete doesn't work.

Related

Can't I change the pointer to another one when I use new operator in C++?

I ask you questions because there is something I don't understand while studying dynamic allocation in C++.
Can I delete "St" and use "ptr" instead if I move the address stored in St to another pointer "ptr" when the dynamically allocated memory is pointed by the St pointer?
If I delete the "St" dynamic allocation, can I move the address to another pointer and delete the "St" immediately because the allocated space does not disappear but disconnects the pointer "St" from the space?
Below is the code I was writing.
Student is a structure.
int main()
{
case 1:
{
Student* ptr = NULL;
Student* St = new Student[10];
ptr = St;
delete[] St;
St = NULL;
break;
}
case 2:`enter code here`
{
printdata(ptr);break;
}
}
Once you've called delete[] on the pointer you get back from new Student[10], the value of that pointer is indeterminate. Both St and ptr are exactly that, but you reassign St. (Since C++11, use nullptr rather than NULL.)
The behaviour of dereferencing the pointer you get back from new Student[10] following the delete[] is undefined.
You can’t use memory you just freed. Memory at that address might still be usable (event till program closes), but there is no guarantee and program might use it for something else.
Can I delete "St" and use "ptr" instead if I move the address stored
in St to another pointer "ptr" when the dynamically allocated memory
is pointed by the St pointer?
If St points toward your array, you can make ptr point toward it as well, but it is not a transfer. What you actually transfer is the adress of the object you are pointing to. The 2 pointers will point toward the same object.
If you delete the object with delete[] (you delete the object, not the pointer), then the 2 pointers will point toward nothing. So what you actually want to do here is make ptr point toward the same object, and then make St point toward null.
Student* ptr = NULL;
Student* St = new Student[10];
ptr = St;
St = NULL;
Edit : If it may help you understand, here is what you can display ...
int x = 4;
int* p = &x;
cout << "x = " << x << " value of x." << endl;
cout << "&x = " << &x << " adress of x." << endl;
cout << "*p = " << *p << " the value of what p points to." << endl;
cout << "p = " << p << " the actual value of p which is the adress of x." << endl;

Copy constructor + Shallow & deep copy

I wanted to ask that when I don't write any copy constructor explicitly so the compiler automatically generates the copy constructor which performs shallow copy by default right?
So in the main() program when I changed the values of integers a, b and pointer p only the value of p changed and values of a and b remain unchanged in the copied object. Why the values of a & b didn't change too? My code is:
#include <iostream>
#include <string.h>
using namespace std;
class Dummy {
private:
int a, b;
int *p;
public:
Dummy() {
p = new int;
}
void setData(int x, int y, int z) {
a = x;
b = y;
*p = z;
}
void showData() {
cout << "a = " << a << " b = " << b;
cout << " p = " << *p << endl;
}
~Dummy() {
delete p;
}
};
int main() {
Dummy d1;
d1.setData(3, 4, 5);
Dummy d2 = d1;
d1.showData();
d2.showData();
d1.setData(6, 7, 8);
d1.showData();
d2.showData();
return 0;
}
The output of my program is:
a = 3 b = 4 p = 5
a = 3 b = 4 p = 5
a = 6 b = 7 p = 8
a = 3 b = 4 p = 8
What I'm saying is while the pointer of object d2 changed when I changed the values of object d1 then why didn't the values of a & b of object d2 changed too?
Also I'm using delete keyword in the destructor to delete the dynamically allocated pointer:
~Dummy() {
delete p;
}
But it's crashing my program instead. Why is that?
You've totally got it wrong - The idea of shallow copy. Actually, c++ does not have anything called deep copy built into itself. So, calling something shallow copy is a bit wrong. And just the use of these words shallow copy creates a lot of confusion too.
Now, let me explain, what happens when cpp performs initialization using assignment. cpp or c(while copying struct) has a concept called bitwise copy. In this concept, all the member variables of one object(struct object/class object - you can say either) is identically copied to another object. Now, it's totally wrong idea that, both objects point to same memory location. In actual, both object has their own memory location and of course, their variables occupy different memory spaces. For you, I have write some tests regarding memory. You would understand perfectly, if you just see the test and it's output:
#include <iostream>
#include <string.h>
using namespace std;
class Dummy {
int a, b;
int *p;
public:
Dummy() {
p = new int;
}
void setData(int x, int y, int z) {
a = x;
b = y;
*p = z;
}
void showData() {
cout << "a = " << a << " b = " << b;
cout << " p = " << *p << endl;
cout << endl; // an extra new line for readability of output
}
void showMemory() {
cout << "addr(a) = " << &a << " addr(b) = " << &b;
cout << " addr(p) = " << &p << endl;
}
~Dummy() {
*p = 100;
delete p;
}
};
// testing memory
void memoryTest() {
cout << "testing d1:" << endl;
Dummy d1;
d1.setData(3, 4, 5);
cout << "addr(d1) = " << &d1 << endl;
d1.showMemory();
cout << endl ;
cout << "testing d2:" << endl;
Dummy d2 = d1;
cout << "addr(d2) = " << &d2 << endl;
d2.showMemory();
}
int main() {
// memoryTest
memoryTest();
return 0;
}
And the output of the test was:
testing d1:
addr(d1) = 0x6dfed4
addr(a) = 0x6dfed4 addr(b) = 0x6dfed8 addr(p) = 0x6dfedc
testing d2:
addr(d2) = 0x6dfec8
addr(a) = 0x6dfec8 addr(b) = 0x6dfecc addr(p) = 0x6dfed0
This clearly shows that, the memory occupied by those two objects d1 and d2 are totally different.
Now, you may have another question remain: Then, why, when i write *p=8, it affects both d1 and d2?:
When you assign, Dummy d2 = d1;, we may say something happended like below(though, it's not actually happen when bitwise copy is applied, it's just for clarity):
d2.p = d1.p
So, we know that, d1.p and d2.p contains the same memory location(note: d1.p is a pointer. so, it does not contain any integer, rather it contains memory address of an int).
So, when you write *p = 8, you are telling the program to go to the memory location targeted by p and change the value of that memory location to 8.(note, here, you didn't change the content of d1.p, d1.p still contains the same memory location. rather, you just changed that memory location's content from 5 to 8). That's why when you call d2.p, you get the changed value. cause, d2.p contains the same memory location as d1.p.
Now, there may have one more question: Why your code crashes when you freed p in destructor?:
Now, let me first ask you, can you free a memory what is already freed. You can write the code, but the behavior is undefined. It may crashes your program or it may do nothing.
Well, in Dummy destructor you've written delete p;. Now, either d2 or d1 would be destroyed first. Let's assume, d2 is destroyed first. So, when d2's destroyer is called, p is freed. Then, d1's destroyer will be called and it'll also try to free p. But p is already freed. And in your case, the program meets a crash for this reason.
Hope, everything is clear to you now.
If anything is not clear about what I've described above, then ask questions, I will try my best to answer them too.

Where to place delete operator for dynamic variable

I am trying to figure out where to place the delete pointerstatement in the program below. I want to clear the memory space that pointer is pointing to in order to avoid memory leaks. It seems that no matter where I put it, I get an error stating:
main(8282,0x7fff95d823c0) malloc: *** error for object 0x7fff582d3960: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
I am not sure how to fix this. Any help is appreciated.
full code:
#include <iostream>
#include <vector>
using namespace std;
int main() {
//initialize vector
vector<int> historyValues;
//initialize pointer and int variable
int *pointer;
pointer = new int;
pointer = 0;
int currentValue;
//make pointer point to the address of currentValue
pointer = &currentValue;
//increment pointer by 1 for a total of 10 times.
//since pointer is pointing at currentValue, currentValue should change also.
//push back the current value of currentValue into the vector.
for (int i = 0; i < 10; i++) {
*pointer += 1;
historyValues.push_back(currentValue);
}
//print final results
cout << "currentValue: " << currentValue << endl;
cout << "*pointer: " << *pointer << endl;
cout << "History of integers stored in currentValue: ";
for (int i = 0; i < historyValues.size(); i++) {
cout << historyValues[i] << " ";
}
cout << endl;
cout << "Program finished" << endl;
return 0;
}
The only place in this program where pointer refers to a dynamic memory block that can be freed is between pointer = new int; and pointer = 0; If you move the delete pointer between those two lines, you'll be fine.
The result of the change is then:
pointer = new int;
delete pointer;
pointer = 0;
However, you might as well just remove all three of those lines and start with pointer = &currentValue; because your code never uses the dynamically allocated int.
Also, your comment "increment pointer" is incorrect. You are incrementing the target of the pointer, not the pointer.

Pointer to a given memory address -C++

basic syntax of pointers: *ptr= &a
here &a will return the memory address of variable a and *ptr will store value of variable a
I want to ask, is it possible to make a pointer return a value from a given memory address? if yes what's the syntax
Yes, you can construct a pointer that refers to some arbitrary address in memory, by initialising the pointer with the address directly, instead of with an expression like &a:
int* ptr = (int*)0x1234ABCD; // hex for convenience
std::cout << *ptr;
Be careful, though, as it is rare that you know such a memory address exactly.
The cast (int*) is required as no implicit conversion exists between int and int*.
Yes. Use the dereference operator *.
For example;
int * a = new int;
int * b = new int;
*a = 5;
// Now a points to a memory location where the number 5 is stored.
b = a; //b now points to the same memory location.
cout << *b << endl; ///prints 5.
cout << a << " " << b << endl; //prints the same address.
int * c = new int;
c = *a;
// Now c points to another memory location than a, but the value is the same.
cout << *c << endl; ///prints 5.
cout << a << " " << c << endl; //prints different addresses.

Why the pointer to single integer memory location can't be deleted?

#include <iostream>
using namespace std;
int main ()
{
int myarray [10];
int * ptr1;
ptr1 = new (nothrow) int [10];
cout << "ptr1 = " << ptr1 << endl;
delete [] ptr1;
cout << "ptr1 = " << ptr1 << endl;
int a = 4;
int * ptr2;
ptr2 = &a;
cout << "ptr2 = " << ptr2 << endl;
delete ptr2;
cout << "ptr2 = " << ptr2 << endl;
return 0;
}
It outputs
ptr1 = 0x9941008
ptr1 = 0x9941008
ptr2 = 0xbfca5cd4
Questions:
1) Why the second print of ptr1 still return the same value? The memory is released but the pointer keeps the memory address value?
2) Why the second print of ptr2 doesn't output?
delete frees the memory, but does not change the value of the pointer. Note however, that the pointer now points to a deallocated area of memory so you should not use it until you reset it.
Your program surely crashes before the second print since you're trying to free a pointer which has not been allocated on the heap. You can only delete areas of memory which you have previously allocated on the heap with the new operator.
1) Because a pointer would still point to the same location. You are printing where it points, not what it points to. It's a description of where the program should find something. If you label a box, and then remove its content, the label (pointer) is still there.
2) You can't delete something that was allocated on the stack.
Deleting a pointer doesn't change the pointer's value. It has essentially two effects:
it destroys the pointed to object. Obviously, destroying an int ha no effect
it announces that the pointed to memory is now unused to memory system
If you want to observe the intpointer being deleted you would need to replace the globel operator new() and operator delete() functions (which may be an interesting experiment but generally nothing you want to do in production code).