使已删除的指针失效

Invalidating deleted pointers?

本文关键字:指针 失效 删除      更新时间:2023-10-16
template<typename T>
someclass<T>& operator=(const someclass<T>& other)
{
    typename std::vector<T *>::const_iterator rhs;
    typename std::vector<T *>::iterator lhs;
    //identity test
    //this->data is std::vector<T *>
    for(lhs = this->data.begin(); lhs != this->data.end(); lhs++)
    {
        delete *lhs;
    }
    this->data.clear(); // this is what I forgot
    this->data.reserve(other.data.size());
    for (rhs = other.data.begin(); rhs != other.data.end(); rhs++)
    {
        if (NULL == *rhs)
        {
            this->data.push_back(NULL);
        }
        else
        {
            this->data.push_back(new T(**rhs));
        }
    }
}

正如您在注释中看到的,我忘记清除数组中的旧指针。当我第二次调用赋值操作符时,我得到了glibc错误,抱怨double free。提供的唯一信息是被删除的地址。

这让我思考如何处理这类被删除的指针——当你不想再次删除它们时,当你这样做时,这肯定是一个错误。您不能将它们设置为NULL,因为另一次删除将是正确的。您不希望保留该值,因为内存位置可以分配给新创建的对象。

对调试有好处的是一些值,比如INVALID,你把它赋给这些指针,说"在这个指针上调用delete是一个错误",而不是NULL,说"在这个指针上调用delete什么也不做"。有这样的东西吗?

No。一个更好的主意是,当您希望拥有所有权语义时,不要使用原始指针。如果您将data的类型设置为boost::ptr_vector<T>std::vector<std::unique_ptr<T>>,那么您将不必手动管理指针的生命周期,并且问题将解决。

您的容器不支持多态对象,因为您所提供的赋值操作符将在容器中的对象分配给另一个容器时对其进行切片。更好的解决方案可能是只使用std::vector<T>。只有当您不考虑指针容器的其他属性(例如指向元素的指针的非无效性,或者可能更快的排序操作)时,这才合适。

解决这个问题的方法是编写不包含任何删除的代码。尽可能使用shared_ptr。当你有一个拥有多态对象的容器时,你也可以使用指针容器。