I'm trying to use SAL annotations to guard against certain possible errors when using reference counted objects. Annotations specific for this use case are not available (as far as I can tell), but using the locking annotations could work.
typedef struct RefCnt;
void
Reference(_Inout_ _Acquires_lock_(*_Curr_) RefCnt *R);
void
Unreference(_Inout_ _Releases_lock_(*_Curr_) RefCnt *R);
This will ensure that for each call to Reference
there is a call to Unreference
, which is exactly what I want.
However, this leaves some gaps. If I have a reference counted object and I have some way of getting that object I want to receive a warning if I'm not unreferencing it:
typedef struct
{
RefCnt R;
} Object;
Object global_obj;
Object *
GetObject(void)
{
Reference(&global_obj.R);
return &global_obj;
}
This will trigger a warning: warning C26165: Possibly failing to release lock 'global_obj.R' in function 'GetObject'.
, which is to be expected. I can annotate the GetObject
function so it becomes: _Acquires_lock_(_Curr_->R) Object *GetObject(void)
. This solves the problem, but I'm probably introducing a new one because I'm not getting any warnings for code like this:
void
Test(void)
{
Object *o = GetObject();
// The reference counter is never reset, this is a leak, I should get a warning
}
If I'm using output parameters it works, so void GetObject(_At_(*_Curr_, _Acquires_lock_(_Curr_->R)) Object **O)
is a solution, but I'm trying to improve an existing API that directly returns the object, so doing this change is something I'd like to avoid.
Is there a way of doing this or is this something that SAL can not express?
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…