gpt4 book ai didi

c++ - Clang 分析器潜在的内存泄漏 - 误报

转载 作者:行者123 更新时间:2023-12-02 09:53:48 26 4
gpt4 key购买 nike

我的代码库中有一个静态函数的实现,并且在运行 clang-tidy 时在它上面,我注意到当我很确定代码正确时,静态分析器指向可能的内存泄漏。 (我已经用 sanitizer 验证过)。我认为这很可能是由于静态分析器缺少一些分支语句,但我不是 100% 确定。

这是代码的精简版本:

#include <array>
#include <functional>
#include <utility>

struct SmallFunction {
struct Base {
virtual ~Base() = default;
virtual void destroy() = 0;
};

template <typename T>
struct Inner : Base {
Inner(T&& f) : f_(std::move(f)) {}
void destroy() override { f_.~T(); }
T f_;
};

template <typename T>
SmallFunction(T&& f) : empty(false) {
static_assert(sizeof(T) <= 32);
new (storage) Inner<T>(std::forward<T>(f));
}

~SmallFunction() {
if (!empty) {
reinterpret_cast<Base*>(storage)->destroy();
}
}

bool empty = true;
alignas(8) char storage[40]; // 32 + 8
};

int main() {
std::array<char, 64> large;
auto lambda = [large] {};
std::function<void()> f = lambda;
SmallFunction sf = std::move(f);
}

这是铿锵有力的分析:
/home/ce/example.cpp:39:1: warning: Potential memory leak [clang-analyzer-cplusplus.NewDeleteLeaks]
}
^
/home/ce/example.cpp:37:29: note: Calling constructor for 'function<void ()>'
std::function<void()> f = lambda;
^
/opt/compiler-explorer/gcc-9.2.0/lib/gcc/x86_64-linux-gnu/9.2.0/../../../../include/c++/9.2.0/bits/std_function.h:675:2: note: Taking true branch
if (_My_handler::_M_not_empty_function(__f))
^
/opt/compiler-explorer/gcc-9.2.0/lib/gcc/x86_64-linux-gnu/9.2.0/../../../../include/c++/9.2.0/bits/std_function.h:677:6: note: Calling '_Base_manager::_M_init_functor'
_My_handler::_M_init_functor(_M_functor, std::move(__f));
^
/opt/compiler-explorer/gcc-9.2.0/lib/gcc/x86_64-linux-gnu/9.2.0/../../../../include/c++/9.2.0/bits/std_function.h:223:4: note: Calling '_Base_manager::_M_init_functor'
{ _M_init_functor(__functor, std::move(__f), _Local_storage()); }
^
/opt/compiler-explorer/gcc-9.2.0/lib/gcc/x86_64-linux-gnu/9.2.0/../../../../include/c++/9.2.0/bits/std_function.h:252:39: note: Memory is allocated
{ __functor._M_access<_Functor*>() = new _Functor(std::move(__f)); }
^
/opt/compiler-explorer/gcc-9.2.0/lib/gcc/x86_64-linux-gnu/9.2.0/../../../../include/c++/9.2.0/bits/std_function.h:223:4: note: Returned allocated memory
{ _M_init_functor(__functor, std::move(__f), _Local_storage()); }
^
/opt/compiler-explorer/gcc-9.2.0/lib/gcc/x86_64-linux-gnu/9.2.0/../../../../include/c++/9.2.0/bits/std_function.h:677:6: note: Returned allocated memory
_My_handler::_M_init_functor(_M_functor, std::move(__f));
^
/home/ce/example.cpp:37:29: note: Returning from constructor for 'function<void ()>'
std::function<void()> f = lambda;
^
/home/ce/example.cpp:39:1: note: Potential memory leak
}
^
1 warning generated.

Here是否启用了 clang-tidy 的 Godbolt 链接。

最佳答案

来自 clang-tidy 的报道肯定有点奇怪,可以做一些澄清。

Inner<T> 的新位置感到不安没有看到匹配的显式析构函数调用。你有这个奇怪的destroy()Base 以来甚至不需要的方法析构函数是虚的,隐含的 Inner析构函数将清理 Inner::f_ .

这可以通过以下方式轻松解决:

  • 替换 bool SmallFunction::emptyBase *SmallFunction::value并将放置新的结果存储在其中。 (这不是绝对必要的,但我发现代码在不需要 reinterpret_cast 的情况下更流畅,而且由于编译器可以进行类型检查,所以更容易正确。)
  • SmallFunction::~SmallFunction , 替换 destroy调用 value->~Base() .
  • 删除 destroy()方法;这不是必需的。

  • 这满足 clang-tidy ( see here )。

    我不认为有内存泄漏,但是有一个对象( Inner<T>)被构造并且从未被破坏。我看不到任何后果,但以正确的方式做事并没有什么坏处——无论如何,它使静态分析器的工作更容易。

    关于c++ - Clang 分析器潜在的内存泄漏 - 误报,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62087533/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com