【问题标题】:Values still accessible after I call delete, c++ [duplicate]在我调用删除后仍然可以访问值,C++ [重复]
【发布时间】:2016-03-07 10:56:07
【问题描述】:

我必须上课,一个Employee 课程和一个BankAccount 课程,员工课程有BankAccount 课程作为私有变量指针。

这就是我想要做的:

  1. 我需要为每个 Employee 中的所有 BankAccounts 设置值
  2. 然后我删除函数末尾的每个Employee 的所有BankAccounts

我使用Employee 中的成员函数设置器来设置BankAccount 指针。 BankAccount 有一个私有变量,即金额。稍后我在应该指向每个BankAccount's 内存地址的指针上调用delete。在我调用 print 查看每个 Employee 的银行值之后,它仍在打印每个 BankAccount 的值

如果我调用 delete 是否不应该删除堆上的内存并且调用 print 时不会为 BankAccount 输出任何内容?

代码如下:

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();
}

打印代码

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
}

银行吸气剂

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

这在 setup_bank 中调用

void Employee::set_bank(Employee* e, double amount){
       bank = new BankAccount(amount);
}

【问题讨论】:

    标签: c++ pointers memory heap-memory


    【解决方案1】:

    如果我调用 delete 是否不应该删除堆上的内存并且调用 print 时不为 BankAccount 输出任何内容?

    没有。

    删除内存中那个位置的对象意味着它不再存在,所以你不能访问它。

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

    因此,您的程序有未定义的行为必须确保不取消引用无效指针!

    【讨论】:

    • 那么,如果它不存在,它怎么能打印出原来的值呢?对它使用删除后,我仍然可以在打印中访问它
    • @user2076774 因为在你还没来得及覆盖它之后得到了内存。 (或者它还没有分配给别的东西)
    • 那么我是否应该在删除“BankAccount”类后调用 set_bank 函数将其设置为空?
    • @user2076774 不,这意味着您不应该自己编写内存管理例程。
    • @user2076774 另外,请阅读stackoverflow.com/a/6445794/106104 的第一部分进行类比。
    【解决方案2】:

    很好地解释了free 的工作原理。

    当您在指针上调用 delete 时,与上面建议的不同,您应该只期待以下内容

    • 执行析构函数

    内存没有设置为零或任何其他神奇的值,因为这是一个非常非常昂贵的操作。何时将调用 free 并且如果这将导致调用 sbrk 在很大程度上取决于实现。后者将内存返回给操作系统。

    例如,众所周知,AIX 有一个相当复杂的mechanism 用于内存管理。您应该期望的是,实际上内存块将被标记为可重新分配,并且新对象可能会在指向地址之后覆盖您的。在这种情况发生之前,你们这些老员工很可能还在。

    另外不像之前说的那样,只要数据段没有被缩减,你就可以很好的访问它,而对象其实还存在,只是只有你自己知道而已。

    这就是为什么在这种情况下您没有得到预期的 SIGSEGV。当您分配某些东西并且对该内存区域中的指针进行寻址执行任意代码时,您可能稍后会得到它。

    访问删除指针是未定义的行为,第二次删除它更加危险。为了缓解这种情况,有很多技术,最简单的是封装和删除类析构函数上的指针。您应该将指针设置为 nullptr。

    简单到此为止,因为您必须应用 rule of three (and a half ) 。因此,最好使用 c++11 提供的共享或唯一指针,暂时忽略这些问题。

    【讨论】:

      猜你喜欢
      • 2016-09-24
      • 2013-04-12
      • 1970-01-01
      • 2011-12-11
      • 1970-01-01
      • 2014-12-13
      • 2012-10-23
      • 2016-11-08
      • 2011-05-23
      相关资源
      最近更新 更多