2

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?

icebp
  • 1,608
  • 1
  • 14
  • 24

0 Answers0