这段代码内存泄漏的原因是什么?

What caused the memory leak in this code?

我正在检查可能导致内存泄漏的代码。我知道 std::set.erase(this) 和 SomeObject 的析构函数有问题。那么如何解决呢?

class SomeObject;
////....
std::set<SomeObject*> managedObjects;
///.....
class SomeObject{
public:
    SomeObject(){  managedObjects.insert(this); }
    SomeObject(SomeObject&& S)/*move cter*/{ managedObjects.insert(this); }
    virtual ~SomeObject() { managedObjects.erase(this); }
    ////....
};
////....
void clearAllObjects() {
    for(auto p : managedObjects){
        if(p){
            delete p;
        }
    }
    managedObjects.clear();
}
////....

当您在 clearAllObjects()delete 时,它将导致 managedObjects.erase(this)managedObjects.erase(p).

相同

这意味着基于for-loop范围内的内部迭代器可能无效(我不确定)。如果是,它将尝试对无效的迭代器执行 ++internal_iterator; - 结果是未定义的行为。

为了安全起见,您可以在执行 erase.

之前复制迭代器并将其移至 set 中的下一个

另请注意:无需检查您 delete 是否为 nullptr。如果是这种情况,标准规定它无效。

示例:

void clearAllObjects() {
    for(auto pit = managedObjects.begin(); pit != managedObjects.end();) {
        delete *pit++ // postfix ++ returns a copy of the old iterator
    }
    
    managedObjects.clear();
}

这个 managedObjects set 的副作用是你不能有 SomeObject.

的自动变量
int main() {
    SomeObject foo;
    clearAllObjects(); // deletes the automatic object "foo" (not allowed)
}                      // <- the automatic object is destroyed here