Очень приятно ловить некоторые действительно очевидные ошибки при использовании неустановленных локальных переменных или при обращении к членам класса или структуры непосредственно перед их инициализацией. В Visual Studio 2008 вы получаете предупреждение «используется неинициализированная локальная переменная» во время компиляции и получаете ошибку проверки во время выполнения в точке доступа при отладке.
Однако, если вы обращаетесь к переменной-члену неинициализированной структуры через одну из ее функций, вы не получите никаких предупреждений или утверждений. Очевидно, что самое простое решение не делай этого, но никто не идеален.
Например:
struct Test
{
float GetMember() const { return member; }
float member;
};
Test test;
float f1 = test.member; // Raises warning, asserts in VS debugger at runtime
float f2 = test.GetMember(); // No problem, just keeps on going
Это удивило меня, но в этом есть какой-то смысл — компилятор не может предположить, что вызов функции для неиспользуемой структуры является ошибкой, или как иначе вы бы инициализировали или сконструировали ее? И все, что может быть интереснее, быстро вызывает так много других сложностей, что имеет смысл не беспокоиться о том, какие функции можно вызывать и когда, особенно просто в качестве помощи при отладке. Я знаю, что могу настроить свои собственные утверждения или проверку ошибок внутри самого класса, но это может усложнить некоторые более простые структуры.
Тем не менее, казалось бы, что в контексте вызова функции, если бы он не знал внутренности GetMember()
тот member
еще не инициализирован? Я предполагаю, что это не только полагаться на статический вывод во время компиляции, учитывая Run-Time Check Failure #3
он повышается во время исполнения, поэтому, исходя из моего текущего понимания, было бы разумно применить те же проверки. Является ли это ограничением этого конкретного компилятора / отладчика (Visual Studio 2008) или более связано с тем, как работает C ++?
Вы, вероятно, заметите, что предупреждение о test
не инициализируется. Вот почему предупреждение & сбой во время выполнения относится только к линии
float f1 = test.member;
Это приводит к неопределенному поведению, и, по крайней мере в режиме отладки, MSVS выполняет некоторую проверку и может вылетать (в выпуске ошибка, вероятно, будет скрыта, и вы просто получите поддельное значение в f1
).
Следующая строка, однако, напрямую не приводит к UB. f1
не читаются и не являются членами данных (напрямую). Вызывается метод, и компилятор не может знать, что функция-член выдаст UB для неинициализированного объекта. Функция может просто напечатать что-то на экран и не читать ни одного из членов, что будет в порядке. Ну и компилятор мог теоретически знаю, потому что он видит код, но он не копает так глубоко. Статический анализатор кода может быть предупредить вас о проблеме.
Других решений пока нет …