1

I have to classes, one Employee class and one BankAccount class, the employee class has the BankAccount class as a private variable pointer.

This is what I am trying to do:

  1. I need to set up all the BankAccounts in each Employee with values
  2. then I delete all BankAccounts for every Employee at the end of the function.

I use a member function setter in Employee to set up the BankAccount pointer. BankAccount has one private variable and that is amount. Later I call delete on a pointer that should point to each BankAccount's memory address. After I call print to see the values of the bank for each Employee and it is still printing values for each BankAccount

If I call delete shouldn't the memory on heap be delete and when print is called not output anything for BankAccount?

Here is the code:

vector<Employee*> employees;

//get employee full name & salary and return
employees.push_back(get_employee_info());

//setup their bank account
setup_bank(employees);

//make temp pointer to store bank memory address
BankAccount * tempBankPtr;

for (int i =0; i < employees.size(); i++) {
    tempBankPtr =employees[i]->get_bank();
    delete tempBankPtr // delete the heap object that pointer is pointing at
}

//print values
for (int i =0; i< employees.size(); i++) {
    employees[i]->print();
}

code for print

void Employee:: print() const {

    cout << "First name is: " << firstName << "\n";
    cout << "Last name is: " << lastName << "\n";
    BankAccount* bankholder = NULL;
    bankholder = get_bank();
    if(bankholder != NULL)
    cout << "Account Balance is: " << get_bank()->get_amount() << "\n"; //prints values
}

getter for bank

BankAccount* Employee::get_bank() const{
    return bank;
}

this is called in setup_bank

void Employee::set_bank(Employee* e, double amount){
       bank = new BankAccount(amount);
}
trincot
  • 317,000
  • 35
  • 244
  • 286
user2076774
  • 405
  • 1
  • 8
  • 21

2 Answers2

11

If I call delete shouldn't the memory on heap be delete and when print is called not output anything for BankAccount?

No.

Deleting the object at that location in memory means it does not exist any more, so you're not allowed to access it.

It does not mean your program will magically print "nothingness" to protect you from this mistake.

Your program therefore has undefined behaviour; you must make sure you do not dereference an invalid pointer!

Community
  • 1
  • 1
Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
  • So if it doesn't exist how is it able to still print the original values that were there? I am still able to access it in print after I used delete on it – user2076774 Dec 03 '15 at 00:24
  • @user2076774 Because whatever got the memory after you hasn't got around to overwriting it yet. (Or it hasn't been allocated to something else yet) – user253751 Dec 03 '15 at 00:26
  • So should I then call a set_bank function that sets the "BankAccount" class to null after I delete it? – user2076774 Dec 03 '15 at 00:30
  • @user2076774 No, it means you shouldn't be writing memory management routines yourself. – Iron Savior Dec 03 '15 at 00:32
  • @user2076774 It's impossible and nonsensical to "set a class to null". – user253751 Dec 03 '15 at 00:34
  • Once you ```delete``` a pointer, there's no guarantee what will be in memory. It could be replaced, or not. This is not your business anymore. It just *happened* to have something. Usually you'd do something: ```delete ptr; ptr= nullptr;``` – Alexandre TryHard Leblanc Dec 03 '15 at 00:34
  • 1
    @user2076774 Also, read the first part of http://stackoverflow.com/a/6445794/106104 for an analogy. – user253751 Dec 03 '15 at 00:34
  • I need to put safety code to prevent deleting the same memory object twice since sometimes two employees can point to the same bank account, is there a way to check if a memory address was deleted before by seeing if the value is NULL? – user2076774 Dec 03 '15 at 00:40
  • `delete null;` and `delete nullptr;` are no-ops, you can just `delete foo; foo = nullptr;`. EDIT: But if the pointer is present in another class that's obviously not going to work; perhaps replace the raw pointer with std::shared_ptr? If you can't do that because your assignment requires you to do manual memory management, implementing your own reference-count handle would be closest to the Right Way. – James Picone Dec 03 '15 at 00:43
  • @user2076774, use smart pointers, they will take care of it for you. – n0rd Dec 03 '15 at 01:02
  • Yeah the assignment is using my own memory management, I guess the count handle would be the best – user2076774 Dec 03 '15 at 01:02
  • @user2076774: _"So should I then call a set_bank function that sets the "BankAccount" class to null after I delete it?"_ Yes. – Lightness Races in Orbit Dec 03 '15 at 01:44
  • @n0rd: No they won't. [Dereferencing a null smart pointer is just as UB as dereferencing a null raw pointer.](http://stackoverflow.com/a/34005605/560648) – Lightness Races in Orbit Dec 03 '15 at 01:44
  • Eh why the downvote o.O – Lightness Races in Orbit Dec 03 '15 at 01:46
1

A very nice explanation of how free works.

When you call delete on the pointer and unlike as it has been suggested above you should only expect the following

  • Execute the destructor

The memory is not set to zero or any other magical value, since that is a very very expensive operation. When free is going to be called and if furthermore this will cause a call to sbrk is largely implementation dependent. The latter returns memory to the operating system.

For example AIX is well known to have a quite complex mechanism for memory management. What you should expect is that actually the block of memory will be marked as reallocatable , and new objects might overwrite your after the address pointed. Until this happens, you old staff are most probably still there.

Furthermore unlike stated before you can very well access it for as long as the data segment has not been reduced, and actually the object still exists , it is just that only you know about it.

That is why in this case you do not get SIGSEGV as you would expect. You probably get it later when you allocate something and the addressing a pointer in that memory area executes arbitrary code.

Accessing a delete pointer is undefined behavior and deleting it a second time is even more dangerous. To alleviate the situation there are many techniques , the most simple being encapsulation and deleting the pointer on the class destructor. You should set the pointer to nullptr.

Simplicity stops here, since you have to apply the rule of three (and a half ) . Thus it is better to work with shared or unique pointer provided by c++11 , and ignore these issues for now.

Community
  • 1
  • 1
g24l
  • 3,055
  • 15
  • 28