2

This simplified example code raises C6001 under static analysis:

struct st_facade
{
    st_facade &operator=(const int new_value) { m_value = new_value; return *this;}

private:
    int m_value;
};

struct foo
{
    st_facade my_int;
};

void main()
{
    foo f;
    f.my_int= 0; // C6001: Using uninitialized memory 'f'.
}

My understanding is that this warning is raised because the overloaded assignment operator hypothetically could be reading uninitialized memory. But in this case, we are not doing that -- we are in fact initializing the memory.

How can I tell the compiler that the assignment operator here is not using any uninitialized memory? I've tried to express this using several different SAL annotations, but nothing has worked.

Zero-initializing the memory (i.e. with foo f{}; or st_facade my_int{};) is not the correct answer in this case. In the actual code, such initialization could have an unacceptable perf impact

[edit] For similar reasons, constructor-based initialization is not the correct answer either. We need this type to be uninitialized on creation; we need to inform the static analyzer that the assignment operator performs the initialization.

[edit 2] More generally, we need a way to tell the static analyzer "this method initializes the object" without implementing a constructor or zero-initializing every instance of the type.

Tim Sparkles
  • 771
  • 6
  • 21
  • re: "could be reading uninitialized memory": perhaps some class might store the incoming value in one of two different fields based on the value of a third field. In that case, the analysis would have correctly identified that we are accessing uninitialized memory when reading the third field. (Though the compiler would not be able to point specifically to that third field without performing more comprehensive analysis than it is currently capable of) – Tim Sparkles Jan 11 '21 at 21:44
  • 1
    Maybe have a (non-explicit) constructor `st_facade(int)` and make it a move assignment `st_facade& operator=(st_facade&&) noexcept = default` instead? – Artyer Jan 11 '21 at 21:51

1 Answers1

0

That's why C++ have constructors.

struct st_facade
{
    explicit st_facade(int value) 
        : m_value{ value } 
    {}
    
    st_facade &operator=(const int new_value) { m_value = new_value; return *this;}

private:
    int m_value;
};

struct foo
{
    explicit foo(int value)
        : my_int{ value }
    {}

    st_facade my_int;
};

int main()
{
    foo f{0};
}
  • 1
    or just add ` = 0;` next to `int m_value` – PiotrNycz Jan 11 '21 at 22:03
  • In 2021 I shouldn't have to leave a warning like this, but PiotrNycz's excellent suggestion requires C++11 or better. – user4581301 Jan 11 '21 at 22:12
  • Zero-initialization and constructor are counter-indicated here. The semantics of the "st_" prefix include "this struct is not initialized by default". I really do need a way to indicate that the assignment operator is write-only. – Tim Sparkles Jan 11 '21 at 23:21