c – 叮当静态分析仪是否通过从unique_ptrs列表中弹出前端而感到
以下C11代码是我认为在cl声中触发假阳性的最小例证:
#include <iostream> #include <list> #include <memory> class ElementType {}; int main(int argc,const char * argv[]) { std::list<std::unique_ptr<ElementType>> theList(5); theList.pop_front(); for (const auto &element: theList) { // (*) std::cout << "This should be fine." << std::endl; } return 0; } 在由星号(*)标记的行上,cl声分析仪声称
解决方法
代码看起来不错,
我检查代码from libc++(相关部分),我相信它只是混淆了静态分析仪. 更多细节: template <class _Tp,class _Alloc> void list<_Tp,_Alloc>::pop_front() { _LIBCPP_ASSERT(!empty(),"list::pop_front() called with empty list"); __node_allocator& __na = base::__node_alloc(); __node_pointer __n = base::__end_.__next_; base::__unlink_nodes(__n,__n); --base::__sz(); __node_alloc_traits::destroy(__na,_VSTD::addressof(__n->__value_)); __node_alloc_traits::deallocate(__na,__n,1); } 列表被实现为循环列表,基于__end_(它是最终指针),因此要获得第一个元素,代码将转到__end _.__ next_. __unlink_nodes的实现是: // Unlink nodes [__f,__l] template <class _Tp,class _Alloc> inline void __list_imp<_Tp,_Alloc>::__unlink_nodes(__node_pointer __f,__node_pointer __l) noexcept { __f->__prev_->__next_ = __l->__next_; __l->__next_->__prev_ = __f->__prev_; } 我们可以用一些简单的ASCII艺术来轻松理解它: Z A B C +---------+ +---------+ +---------+ +---------+ --| __prev_ |<--| __prev_ |<--| __prev_ |<--| __prev_ |<- ->| __next_ |-->| __next_ |-->| __next_ |-->| __next_ |-- +---------+ +---------+ +---------+ +---------+ 要从此列表中删除范围A-B: > Z .__ next_必须指向C 因此,调用__unlink_nodes(A,B)将: >取A .__ prev _.__ next_(即Z .__ next_),并将其指向B .__ next_(即C) 这很简单,甚至在使用单个元素范围(这里是这种情况)调用时也可以使用). 然而,现在请注意,如果列表为空,那根本就不行! __list_node_base的默认构造函数是: __list_node_base() : __prev_(static_cast<pointer>(pointer_traits<__base_pointer>::pointer_to(*this))),__next_(static_cast<pointer>(pointer_traits<__base_pointer>::pointer_to(*this))) {} 也就是说它是指自己.在这种情况下,__unlink_nodes用& __ end_(两次)调用,不会更改__end _.__ prev _.__ next_ = __end _.__ next_是幂等的(因为__end_.prev是__end_本身). 可能是: >分析仪考虑到一个空列表的情况(_LIBCPP_ASSERT正在编译出来) 或者也许这是指针跳舞的其他东西…希望Clang团队能够补丁. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |