Skip to content

[Clang SA] Potential leak of memory in lambda capture (cplusplus.NewDeleteLeaks) #55219

@igagis

Description

@igagis

to reproduce

create file main.cpp with contents:

#include <memory>
#include <iostream>

int main(int argc, const char** argv){

	auto f = [c = std::make_shared<int>(10)](){
			return *c + 3;
		};

	auto i = f();
	std::cout << "i = " << i << std::endl;

	return 0;
}

run clang-tidy with command:

clang-tidy main.cpp -- -std=c++17

expected result

no warnings generated

actual result

/home/ivan/prj/test/main.cpp:14:1: warning: Potential leak of memory pointed to by field '_M_pi' [clang-analyzer-cplusplus.NewDeleteLeaks]
}
^
/home/ivan/prj/test/main.cpp:6:16: note: Calling 'make_shared<int, int>'
        auto f = [c = std::make_shared<int>(10)](){
                      ^
/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/shared_ptr.h:875:14: note: Calling 'allocate_shared<int, std::allocator<int>, int>'
      return std::allocate_shared<_Tp>(std::allocator<_Tp_nc>(),
             ^
/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/shared_ptr.h:859:14: note: Calling constructor for 'shared_ptr<int>'
      return shared_ptr<_Tp>(_Sp_alloc_shared_tag<_Alloc>{__a},
             ^
/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/shared_ptr.h:408:4: note: Calling constructor for '__shared_ptr<int, __gnu_cxx::_S_atomic>'
        : __shared_ptr<_Tp>(__tag, std::forward<_Args>(__args)...)
          ^
/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/shared_ptr_base.h:1371:14: note: Calling constructor for '__shared_count<__gnu_cxx::_S_atomic>'
        : _M_ptr(), _M_refcount(_M_ptr, __tag, std::forward<_Args>(__args)...)
                    ^
/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/shared_ptr_base.h:680:19: note: Calling '__allocate_guarded<std::allocator<std::_Sp_counted_ptr_inplace<int, std::allocator<int>, __gnu_cxx::_S_atomic>>>'
          auto __guard = std::__allocate_guarded(__a2);
                         ^
/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/allocated_ptr.h:97:21: note: Calling 'allocator_traits::allocate'
      return { __a, std::allocator_traits<_Alloc>::allocate(__a, 1) };
                    ^
/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/alloc_traits.h:460:16: note: Calling 'new_allocator::allocate'
      { return __a.allocate(__n); }
               ^
/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/ext/new_allocator.h:105:2: note: Taking false branch
        if (__n > this->_M_max_size())
        ^
/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/ext/new_allocator.h:109:2: note: Taking false branch
        if (alignof(_Tp) > __STDCPP_DEFAULT_NEW_ALIGNMENT__)
        ^
/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/ext/new_allocator.h:115:27: note: Memory is allocated
        return static_cast<_Tp*>(::operator new(__n * sizeof(_Tp)));
                                 ^
/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/alloc_traits.h:460:16: note: Returned allocated memory
      { return __a.allocate(__n); }
               ^
/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/allocated_ptr.h:97:21: note: Returned allocated memory
      return { __a, std::allocator_traits<_Alloc>::allocate(__a, 1) };
                    ^
/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/shared_ptr_base.h:680:19: note: Returned allocated memory
          auto __guard = std::__allocate_guarded(__a2);
                         ^
/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/shared_ptr_base.h:1371:14: note: Returning from constructor for '__shared_count<__gnu_cxx::_S_atomic>'
        : _M_ptr(), _M_refcount(_M_ptr, __tag, std::forward<_Args>(__args)...)
                    ^
/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/shared_ptr.h:408:4: note: Returning from constructor for '__shared_ptr<int, __gnu_cxx::_S_atomic>'
        : __shared_ptr<_Tp>(__tag, std::forward<_Args>(__args)...)
          ^
/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/shared_ptr.h:859:14: note: Returning from constructor for 'shared_ptr<int>'
      return shared_ptr<_Tp>(_Sp_alloc_shared_tag<_Alloc>{__a},
             ^
/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/shared_ptr.h:875:14: note: Returned allocated memory
      return std::allocate_shared<_Tp>(std::allocator<_Tp_nc>(),
             ^
/home/ivan/prj/test/main.cpp:6:16: note: Returned allocated memory
        auto f = [c = std::make_shared<int>(10)](){
                      ^
/home/ivan/prj/test/main.cpp:14:1: note: Potential leak of memory pointed to by field '_M_pi'
}
^

version

$ clang-tidy --version
LLVM (http://llvm.org/):
  LLVM version 11.0.1
  
  Optimized build.
  Default target: x86_64-pc-linux-gnu
  Host CPU: haswell

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions