【问题标题】:Am I deleting this pointer correctly?我是否正确删除了这个指针?
【发布时间】:2011-02-17 06:51:23
【问题描述】:

我有以下代码:

LPWSTR pszDSPath = NULL;
pszDSPath = new WCHAR[  wcslen(pwszFilter)+
                        wcslen(wstrServer.c_str())+
                        wcslen(var.bstrVal) +
                        1
                     ];

// ....
// ....

if(pszDSPath)
{
    delete pszDSPath; 
    pszDSPath = NULL;
}

上面的代码会产生内存泄漏吗?我不确定我是否正确删除了pszDSPath

【问题讨论】:

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


【解决方案1】:

您没有使用正确的deletenew 有两种形式:创建单个对象的标量 new(例如 new int)和创建数组的数组 new(例如 new int[42])。

同样,delete 有两种形式:deletedelete[]。如果使用new,则必须使用delete 销毁对象,如果使用new[],则必须使用delete[] 销毁对象。

由于你已经使用new[]创建了pszDSPath指向的对象,你必须使用delete[] pszDSPath来销毁该对象。

但是请注意,如果您只使用std::vector,这将变得更容易:

std::size_t n = wcslen(pwszFilter)+
                wcslen(wstrServer.c_str())+
                wcslen(var.bstrVal) +
                1;

std::vector<WCHAR> v(n);

// &v[0] can be used as you are using pszDSPath in your current code.

在 C++ 中,您应该避免手动管理内存:要做到正确非常困难,而且需要大量工作。 C++ 标准库中有一些库工具,包括像std::vectorstd::map 这样的容器以及像std::auto_ptrstd::unique_ptrstd::shared_ptr 这样的智能指针,它们可以为您管理对象的生命周期。你不应该做比你必须做的更多的工作:如果你认为你必须在代码中的某处写delete,那么你的代码可能是错误的。

使用容器管理资源生命周期的这一原则基于一种称为范围绑定资源管理 (SBRM) 或 Resource Acquisition is Initialization (RAII) 的设计模式。

(std::unique_ptr 是 C++0x 的一部分,旨在取代 std::auto_ptr,您的编译器可能还不支持它。std::shared_ptr 也是 C++0x 的一部分,但它已可用于作为 Boost 库的一部分(boost::shared_ptr)大约十年,并包含在 C++ TR1 中。)

【讨论】:

  • 感谢 James 的详细回复,但有一点让我很困惑,Jonathan Wood 在他的评论中也提到,对于字符指针,使用“delete pszDSPath”或"删除 [] psdDSPath"
  • @RizWiz:乔纳森伍德的回答中的那句话是不正确的。您必须将new[]delete[] 正确匹配。如果你不这样做,那么你的程序的行为是未定义的,这意味着你的程序可能会崩溃,或者你的数据可能会损坏,或者事情可能看起来工作了几个月然后突然停止工作。
  • “特别难”有点夸张了吧?
  • @Jörgen:一点也不。在 C 中手动管理资源既繁琐又困难,但在 C 中您没有太多选择。在 C++ 中要困难 100 倍或 1000 倍,它增加了非本地控制流(异常)和隐式调用函数(尤其是构造函数、析构函数和重载运算符)。不仅手动管理资源的代码更难正确编写,而且验证这些代码是否正确、对代码进行推理以及在不破坏代码的情况下对其进行修改和维护也非常困难。
  • 也许我们对extraordinally这个词的含义有不同的看法。我同意“手动”跟踪分配的资源比使用一些受 RAII 启发的机制更乏味且更容易出错,但我不会称之为困难。构建机器人是我认为的困难。
【解决方案2】:

使用delete[] pszDSPath 来避免预先分配数组时的内存泄漏。

【讨论】:

    【解决方案3】:

    使用delete[] 来避免未定义的行为。

    但是在你的情况下使用deletealmost never cause a memory leak alone - 要么它会正常工作,要么你会得到比内存泄漏更糟糕的东西。不要冒险 - 使用delete[]

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-14
      • 1970-01-01
      • 2012-09-27
      • 1970-01-01
      • 1970-01-01
      • 2015-02-03
      相关资源
      最近更新 更多