C ++测试示例中可能存在的逻辑缺陷

时间:2012-10-08 16:41:06

标签: c++ memory memory-management memory-leaks

在我的大学里,有一个用C ++进行的实际编程测试 - 而且我坚持一个例子,我不确定这个问题是否有效并且可以正确完成。

(简单)任务:

  • 完成Person的析构函数,以便再次释放已分配的name

  • 在main函数中,将//???替换为释放先前分配的内存所需的语句

起初,这些任务对我来说似乎微不足道:对于析构函数,只需编写delete[] name并在main函数中使用delete[] friends。据推测,这也是本例作者的意思。

然而

此代码示例中似乎存在缺陷,导致内存泄漏以及析构函数被多次调用。

person类没有赋值operator =,这意味着现有的Person对象(例如maria)被分配给main函数中friends数组中的插槽,内部已分配{ {1}}未被复制。所以两个对象现在共享相同的内部name指针!此外,指向先前驻留在所述数组槽中的char*名称的指针永久丢失,导致不可避免的内存泄漏。

当调用Person时 - 数组中的对象被销毁 - 导致他们的析构函数被调用并释放他们的delete[] friends;成员。但是,当程序结束时,name范围内的本地Person对象被破坏 - 当然它们的main成员仍然指向之前已经释放的内存。

实际问题:

  • 这个测试示例是否有缺陷,或者我错过了什么?
  • 如果完全坚持执行给定的任务(只改变析构函数的实现,并在主函数的注释部分插入新代码),可以解决上面列出的问题吗?

...

name

3 个答案:

答案 0 :(得分:5)

你是对的。您可以通过仅在指定位置进行更改来修复它,但它们会变得相当极端:

用析构函数替换析构函数中的//...

    delete[] name;
}

Person& operator=(const Person& other)
{
    if (this != &other) {
        delete[] name;  // not completely exception-safe!
        name = new char[strlen(other.name)+1];
        strcpy(other.name,name);
    }
    return *this;

另一个严重的问题是使用重新排序参数的新定义重新定义标准函数(strcpy)。

(另请参阅:SQL注入攻击,它还会导致现有的语法元素对,频繁的引号和括号与插入的语法元素重新配对)

答案 1 :(得分:2)

  1. 是的,测试示例存在缺陷,可能是有意识地完成的。类Person肯定需要赋值运算符,请记住Rule Of Three
  2. 不,这是不可能的。默认的编译器生成的赋值运算符将泄漏由friends数组中的对象分配的内存和双重删除由自动Person对象分配的内存。

答案 2 :(得分:-1)

对于每一个新的应该有一个删除[]。