Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/136.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
通过使用新指针放置此指针导致的C++内存泄漏?_C++ - Fatal编程技术网

通过使用新指针放置此指针导致的C++内存泄漏?

通过使用新指针放置此指针导致的C++内存泄漏?,c++,C++,正如我们所知,placement new只构造一个对象,而不分配任何内存。另外,类资源中的所有成员都是对象,而不是指针,尽管std::string内部包含一个动态数组,当std::string对象被销毁时,该数组将被释放。并且*这指向堆栈上分配的内存,这意味着将始终调用析构函数。所以我认为placement new在这里所做的只是覆盖原始对象。下面是一个简单的例子。当我在VS2019上运行这个示例时,内存使用量一直在增加 class Resource { public: Resource

正如我们所知,placement new只构造一个对象,而不分配任何内存。另外,类资源中的所有成员都是对象,而不是指针,尽管std::string内部包含一个动态数组,当std::string对象被销毁时,该数组将被释放。并且*这指向堆栈上分配的内存,这意味着将始终调用析构函数。所以我认为placement new在这里所做的只是覆盖原始对象。下面是一个简单的例子。当我在VS2019上运行这个示例时,内存使用量一直在增加

class Resource
{
public:
    Resource() {};
    Resource(const std::string& s) : str(s)
    {
        new(this)Resource();
    }
    

private:
    std::string str;

}; 


int main()
{
    while (true)
        Resource resource("hello");
}

最新的标准草案说:

[基本生活]

程序可以通过重用对象占用的存储来结束任何对象的生命周期。。。如果没有显式调用析构函数,或者如果没有使用删除表达式释放存储,则不会隐式调用析构函数,并且依赖析构函数产生的副作用的任何程序都具有未定义的行为

因此,由于构造函数对动态对象重用*this的存储,而不调用原始对象的析构函数,因此该析构函数永远不会被调用。该析构函数是销毁字符串成员并释放其内存的位置


结论:不要把新的内容放在这上面。

最新的标准草案说:

[基本生活]

程序可以通过重用对象占用的存储来结束任何对象的生命周期。。。如果没有显式调用析构函数,或者如果没有使用删除表达式释放存储,则不会隐式调用析构函数,并且依赖析构函数产生的副作用的任何程序都具有未定义的行为

因此,由于构造函数对动态对象重用*this的存储,而不调用原始对象的析构函数,因此该析构函数永远不会被调用。该析构函数是销毁字符串成员并释放其内存的位置


结论:不要在*this上放置new。

在放置new:this->~Resource;之前调用析构函数;。在这里使用placement new基本上只是在旧字符串上复制memcopies,这意味着旧字符串的内容丢失。因为短字符串优化可能需要比hello更长的字符串才能在某些平台上消除错误。实际上,大多数情况下。如果内存用于实现细节,64位平台在动态分配内存之前可以容纳21个字符加上终止符,而在32位平台上可以容纳9个字符加上终止符。不过,在分配STR后构建此布局时,我有点不以为然……应该没有理由在这上面使用新的布局;您可以简单地使用一个委托构造函数到默认构造函数,这将具有相同的效果,因为您将立即清除给定给它的值str@DanielLangr为一个生命周期尚未开始的对象调用析构函数确实是错误的。我怀疑这种构造的合法性与在构造函数中对此使用placement new是一样的,不过正如公认的答案所解释的那样。在placement new之前调用析构函数:this->~Resource;。在这里使用placement new基本上只是在旧字符串上复制memcopies,这意味着旧字符串的内容丢失。因为短字符串优化可能需要比hello更长的字符串才能在某些平台上消除错误。实际上,大多数情况下。如果内存用于实现细节,64位平台在动态分配内存之前可以容纳21个字符加上终止符,而在32位平台上可以容纳9个字符加上终止符。不过,在分配STR后构建此布局时,我有点不以为然……应该没有理由在这上面使用新的布局;您可以简单地使用一个委托构造函数到默认构造函数,这将具有相同的效果,因为您将立即清除给定给它的值str@DanielLangr为一个生命周期尚未开始的对象调用析构函数确实是错误的。我怀疑这种构造的合法性与在构造器中使用新的布局是一样的,尽管正如公认的答案所解释的那样。