My initial approach would be to create an instrumented build adding debug where the value is changed. If the attribute was private in a class, I could just manipulate the mutator to log where the issue was happening. Unfortunately, it's been implemented as a public attribute in a struct and there are literally hundreds of places where I would need to refactor to replace direct use with a mutator, or other instrumented code.
One of the key features of C++'s type system is that you can write classes which behave syntactically the same as built-in types.
So, instead of moving the field behind a mutator, just replace the field with a class instance which has the appropriate assignment operator (this is your mutator). Add whatever other operators and constructors are necessary. If you do this correctly, no calling code needs to change at all, only to be recompiled.
You can see an example of a suitable assignment operator in the BoundedValue validating type wrapper I wrote elsewhere:
template <typename T, int Tmin, int Tmax> class BoundedValue
{
T val_;
public:
enum { min_value=Tmin, max_value=Tmax };
// ...
// run-time checked assignment:
BoundedValue& operator= (T const& val) {
BOUNDED_VALUE_ASSERT(min_value, max_value, val); // or whateveryour check you needhere
val_ = val;
return *this;
}
};