I have a piece of C 20 code that I believe is valid, but our static analyzer thinks it's unsafe.
struct Foo {
explicit Foo() { activeFoo = this; }
~Foo() { activeFoo = nullptr; }
Foo(const Foo&) = delete;
Foo(Foo&&) = delete;
inline static const Foo* activeFoo = nullptr;
};
Foo makeFoo()
{
// Is there a dangling reference here?
return Foo();
}
int main()
{
auto myFoo = makeFoo();
}
My static analyzer thinks makeFoo
causes activeFoo
to point to a temporary object and will become a dangling pointer. I believe this is wrong; the return Foo();
should get a guaranteed copy elision (as evidenced by the deleted copy & move constructors), so there is only ever one Foo
instance constructed, myFoo
.
Who is correct?
CodePudding user response:
makeFoo
and copy elision (which as you noted is guaranteed in this specific example since C 17) don't even matter.
activeFoo
can never be dangling. If it was pointing to an object after its lifetime ended, then the destructor of that object would have reset activeFoo
to nullptr
, meaning it cannot be pointing to the object, a contradiction. That is assuming the destructor is called for every created object of type Foo
. Technically this might not always be the case if you placement-new objects explicitly, although it should.
I would however not generally expect a static analyzer to figure out this logic. Without some details on the static analyzer or what exactly it complains about, it will be hard to say more.