自定义共享指针上的Clang Analyzer,是否为假肯定

时间:2018-11-24 08:40:22

标签: c++ clang shared-ptr clang-static-analyzer

Clang静态分析器在通过共享ptr的以下实现释放后报告了内存使用情况(虽然天真,但仍然可以正常工作):

template <class T>
class Shared
{
public:
    Shared()
       : ptr(0) , count(0)
    {
    }

explicit Shared(T* otherPtr)
    : ptr(0), count(0)
{
    init(otherPtr);
}

template <class DerivedT>
explicit Shared(DerivedT* otherPtr)
    : ptr(0), count(0)
{
    init(otherPtr);
}

explicit Shared(OutRef<T> ref)
    : ptr(0), count(0)
{
    init(ref.ptr);
}

Shared(const Shared& other)
    : ptr(other.ptr), count(other.count)
{
    addShared();
}

template <class DerivedT>
Shared(const Shared<DerivedT>& other)
    : ptr(other.ptr), count(other.count)
{
    addShared();
}

Shared& operator = (const Shared& other)
{
    Shared tmp(other);
    swap(tmp);
    return *this;
}

template <class DerivedT>
Shared& operator = (const Shared<DerivedT>& other)
{
    Shared tmp(other);
    swap(tmp);
    return *this;
}

~Shared()
{
    destroy();
}

operator bool() const
{
    return ptr != 0;
}

void operator = (T* otherPtr)
{
    set(otherPtr);
}

template <class DerivedT>
void operator = (DerivedT* otherPtr)
{
    set(otherPtr);
}

void operator = (OutRef<T> ref)
{
    set(ref.ptr);
}

T* operator->()
{
    return ptr;
}

const T* operator->() const
{
    return ptr;
}

T& operator*()
{
    return *ptr;
}

const T& operator*() const
{
    return *ptr;
}

template <class DerivedT>
void set(DerivedT* otherPtr)
{
    if (ptr != otherPtr)
    {
        destroy();
        init(otherPtr);
    }
}

T* get()
{
    return ptr;
}

const T* get() const
{
    return ptr;
}

operator T*()
{
    return ptr;
}

operator const T*() const
{
    return ptr;
}

template <class TT>
Shared<TT> cast()
{
    Shared<TT> result;
    result.ptr = (TT*)ptr;
    result.count = count;
    result.addShared();
    return result;
}

bool isLastOwner() const
{
    return count && *count == 1;
}

private:
void addShared()
{       
    if (count)
    {
        *count += 1;
    }
}

template <class DerivedT>
void init(DerivedT* otherPtr)
{
    presume(ptr == 0);
    presume(count == 0);
    if (otherPtr == 0)
    {
        return;
    }
    ptr = otherPtr;
    count = new Index(1);
}

void destroy()
{
    if (count)
    {
        *count -= 1;

        if (*count == 0)
        {
            presume(sizeof(T) > 0); //will break compilation in case of undefined T
            delete ptr;
            delete count;
        }
    }
    ptr = 0;
    count = 0;
}

void swap(Shared& other)
{
    Swap(ptr, other.ptr);
    Swap(count, other.count);
}

private:
   T* ptr;
   Index* count;

   template <class OtherT> friend class Shared;
};

例如,如果我具有Shared f()函数并将其用作

Shared<X> a = f();
a->callSomeMethod();

在释放内存后,我得到静态分析器警告“ a”已使用。基本上,它检测到已调用destroy()方法,但无法检测到堆栈跟踪中的计数器为正(对于计数器零检查,它写入“假定条件为true”)。是否可以添加一些assert()以便它了解计数器在此处为正?还是真的是不正确的共享指针实现?

0 个答案:

没有答案