c – 叮当静态分析仪是否通过从unique_ptrs列表中d出前端而感到困惑?

c – 叮当静态分析仪是否通过从unique_ptrs列表中d出前端而感到困惑?,第1张

概述以下C11代码是我认为在cl声中触发假阳性的最小例证: #include <iostream>#include <list>#include <memory>class ElementType {};int main(int argc, const char * argv[]) { std::list<std::unique_ptr<ElementType>> theList( 以下C11代码是我认为在cl声中触发假阳性的最小例证: @H_502_2@#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声分析仪声称

…filePath…/main.cpp:21:29: Use of memory after it is freed (within a call to ‘begin’)

就我的解释而言,这段代码是无害的,但是cl ang不满,std :: List< T> :: pop_front()不仅调用其元素的析构函数,而且还会移动std :: List< ; T> ::开始().通过pop_back替换对pop_front的调用,使分析仪警告消失,甚至通过erase(theList.begin())替换它使它无警告地出现. 我错过了一些事情,还是绊倒了一个错过的案子? 以供参考:
这些结果来自Mac OS X 10.9.2上的XCode 5.1.1(5B1008)

@H_502_2@$clang --versionApple LLVM version 5.1 (clang-503.0.40) (based on LLVM 3.4svn)Target: x86_64-apple-darwin13.1.0Thread model: posix
解决方法 代码看起来不错,

我检查代码from libc++(相关部分),我相信它只是混淆了静态分析仪.

更多细节:

@H_502_2@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的实现是:

@H_502_2@// 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艺术来轻松理解它:

@H_502_2@Z A B C +---------+ +---------+ +---------+ +---------+--| __prev_ |<--| __prev_ |<--| __prev_ |<--| __prev_ |<-->| __next_ |-->| __next_ |-->| __next_ |-->| __next_ |-- +---------+ +---------+ +---------+ +---------+

要从此列表中删除范围A-B:

> Z .__ next_必须指向C
> C .__ prev_必须指向Z

因此,调用__unlink_nodes(A,B)将:

>取A .__ prev _.__ next_(即Z .__ next_),并将其指向B .__ next_(即C)
>取B .__下一个_.__ prev_(即C .__ prev_),并将它指向A .__ prev_(即Z)

这很简单,甚至在使用单个元素范围(这里是这种情况)调用时也可以使用).

然而,现在请注意,如果列表为空,那根本就不行! __List_node_base的默认构造函数是:

@H_502_2@__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正在编译出来)
>并得出结论,在这种情况下,__end _.__ next_(由begin()使用)在pop_front()中的deallocate()调用留下悬挂,

或者也许这是指针跳舞的其他东西…希望Clang团队能够补丁.

总结

以上是内存溢出为你收集整理的c – 叮当静态分析仪是否通过从unique_ptrs列表中d出前端而感到困惑?全部内容,希望文章能够帮你解决c – 叮当静态分析仪是否通过从unique_ptrs列表中d出前端而感到困惑?所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1252081.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-07
下一篇 2022-06-07

发表评论

登录后才能评论

评论列表(0条)

保存