【问题标题】:Would calling the default parameter with `new` cause memory leak?用`new`调用默认参数会导致内存泄漏吗?
【发布时间】:2021-01-26 04:16:15
【问题描述】:

我正在尝试编写一个返回最大检测对象中心点的函数。这里没问题。问题是,如果用户想使用它,我还想从参数中返回前景掩码。

为了处理这种情况,我的解决方案如下:

cv::Point detect(const cv::Mat &img, cv::Mat &mask = *new cv::Mat());

如果指定了mask参数,则可以在main中使用。 RAII 在其他情况下是否有效,还是会出现内存泄漏?

注意:我知道我可以将函数重载2行,但我想知道是否可以通过使用默认参数而不是使用指针来正确执行(输入类型是严格的) .

另外说明:如果可以使用cv::noArray()或者类似的函数,那完全没问题。

示例用法:

char ch = 0;
while (ch != 27) // ESC is pressed
{
    cap >> img;
    if (img.empty())
        break;
    cv::Mat mask;
    cv::Point pt = detect(img, mask);
    // or pt = detect(img);
    cv::imshow("original", img);
    cv::imshow("foreground", mask);
    ch = cv::waitKey(1);
}

【问题讨论】:

  • 不可能说。代码可以删除底层指针,在这种情况下没有泄漏。但这很糟糕。不要这样做。
  • RAII 是一种您必须实现的设计模式,它不是 C++ 免费强制执行的。我假设如果用户传递了mask 的值,您不会删除detect 末尾的cv::Mat,这意味着您确实会有内存泄漏。只需拿一个指针并使用cv::Mat* p_Mask = nullptr 或其他东西,如果您希望他们能够在没有掩码的情况下调用它。
  • 内存泄漏不是你通过new创建东西的地方,而是你错过删除它的地方。
  • x = *new X 几乎永远不会正确,不要那样做。
  • @Burak VC++ 有一个允许它的非标准和不可移植的扩展。

标签: c++ memory-leaks default-parameters opencv-mat


【解决方案1】:

是的,这会导致内存泄漏。您可以考虑使用元组返回值:

std::tuple<cv::Point, cv::Mat> detect(const cv::Mat &img);

或将mask 设为指针:

cv::Point detect(const cv::Mat &img, cv::Mat *mask = nullptr);

您也可以尝试使用演员表保持相同的签名。这很难看,但它可能会起作用:

cv::Point detect(const cv::Mat &img, cv::Mat &mask = const_cast<cv::Mat&>(static_cast<cv::Mat const&>(cv::Mat())));

【讨论】:

【解决方案2】:

丑,但没有内存泄漏:

cv::Point detect(const cv::Mat &img, cv::Mat &mask = *std::make_unique<cv::Mat>());

如果用户不提供掩码,则会创建一个掩码。 detect 会将掩码写回,然后立即销毁。使用重载会更有效,因为它可以跳过不必要的更新。

或者,使用cv::Mat* mask = nullptr。我不知道您所说的“(输入类型是严格的)”是什么意思。但是对于有经验的 C++ 程序员来说,cv::Mat* mask = nullptr 模式很明确:可选的 out 参数,没有隐含的所有权转移。

【讨论】:

  • 嗯,它需要额外的 memory 库和 C++14。最重要的是,GCC 版本至少应该是 5。cmake_minimum_required(VERSION 3.14.0)source 对于这么简单的功能,这些都是非常高的先决条件。
  • 我不使用指针,因为 OpenCV OutputArray 就是这样使用的。例如,请参阅Canny Edge Detector
  • @Burak:嗯,我们现在是 C++17/20,而且是 GCC 10,所以 C++14/GCC 5 似乎并不合理。无论哪种方式,您都可以只使用 C++11 中的底层 std::unique_ptr&lt;cv::Mat&gt;,或者返回 way 上个世纪的 Boost 和 C++98。
  • APT在Ubuntu 18.04上安装的CMake版本目前为3.10.2。
  • 有趣的是make_shared 需要 C++11 而make_unique 是 C++14 标准。 Shared 通常更适用,我希望反过来。
猜你喜欢
  • 1970-01-01
  • 2017-09-11
  • 1970-01-01
  • 2010-11-18
  • 2021-03-23
  • 2021-09-25
  • 2014-12-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多