Я ищу простой способ найти неинициализированные переменные-члены класса.
Поиск их во время выполнения или времени компиляции в порядке.
В настоящее время у меня есть точка останова в конструкторе класса и поочередно проверяю переменные-члены.
Я ищу простой способ найти неинициализированные переменные-члены класса.
Поиск их во время выполнения или времени компиляции в порядке.
В настоящее время у меня есть точка останова в конструкторе класса и поочередно проверяю переменные-члены.
Если вы используете GCC, вы можете использовать флаг -Weffc++
, который генерирует предупреждения, когда переменная не инициализируется в списке инициализации члена. Это:
class Foo
{
int v;
Foo() {}
};
Приводит к:
$ g++ -c -Weffc++ foo.cpp -o foo.o
foo.cpp: In constructor ‘Foo::Foo()’:
foo.cpp:4: warning: ‘Foo::v’ should be initialized in the member initialization list
Один недостаток заключается в том, что -Weffc++
также предупреждает вас, когда переменная имеет правильный конструктор по умолчанию и инициализацию, поэтому не требуется. Он также предупредит вас, когда вы инициализируете переменную в конструкторе, но не в списке инициализации члена. И он предупреждает о многих других проблемах стиля С++, таких как отсутствующие конструкторы-копии, поэтому вам может понадобиться немного очистить свой код, если вы хотите регулярно использовать -Weffc++
.
Существует также ошибка, которая приводит к тому, что она всегда дает вам предупреждение при использовании анонимных объединений, которые в настоящее время вы не можете обойти, а затем отключить предупреждение, что можно сделать с помощью
#pragma GCC diagnostic ignored "-Weffc++"
В целом, однако я обнаружил, что -Weffc++
невероятно полезен в улавливании множества распространенных ошибок С++.
Valgrind может рассказать вам, есть ли в Linux.
Valgrind (бесплатно, в Linux) и Purify (в Windows) найти неинициализированные переменные, недопустимые указатели и т.д., запустив свой код на специальной виртуальной машине.
Это прост в использовании и чрезвычайно мощный; он, вероятно, найдет много ошибок за пределами очевидных неинициализированных переменных.
Coverity, Klocwork и Lint может найти неинициализированные переменные, используя статический анализ кода.
cppcheck найдет это.
-Wuninitialized
?
(Это только проверяет, используется ли переменная неинициализирована, т.е. если
struct Q {
int x, y;
Q() : x(2) {}
int get_xy() const { return x*y; }
};
g++ будет предупреждать, только когда пользователь вызывает get_xy()
без назначения y
.)
Visual Studio (MSVC) имеет параметр компилятора /sdl (Включить дополнительные проверки безопасности) (http://msdn.microsoft.com/en-us/library/jj161081.aspx). Во время выполнения это:
Выполняет инициализацию члена класса. Автоматически инициализирует класс члены типа указателя равны нулю при создании объекта (до конструктор работает). Это помогает предотвратить использование неинициализированных данных связанные с членами класса, что конструктор явно не инициализации.
Это не поможет вам обнаружить неинициализированные переменные-члены во время компиляции, но это делает поведение более предсказуемым, когда оно происходит во время выполнения. Вы, конечно, не должны писать код, который полагается на этот параметр.
Если вы используете Visual Studio, вы можете скомпилировать ее в режиме отладки, остановить программу в отладчике и искать, какие переменные инициализируются байтами, содержащими 0xCC (стек) или 0xCD (куча).
Хотя лично я инвестировал в инструмент статического анализа для более тщательного подхода.
/проанализировать в Visual Studio ( "Team System" )
Осторожно! Варианты компилятора, предложенные здесь, не являются ни надежными, ни независимыми от версии. Рассмотрим простой пример:
class A {
int a;
public:
void mA() {
printf("haha");
++a;
int g = 2/a;
printf("%i\n",g);
}
};
int main() {
A a;
a.mA();
}
Скомпилировано с помощью g++ -O3 -Weffc++ -Wuninitialized
эта информация сообщает uninitialized
о версиях gcc до 4.6 включительно и успешно передается на 4.7 и 4.8 (проверена на MacPorts). Тогда, как ни странно, если мы удалим printf("haha");
, то как 4.7, так и 4.8 вдруг увидим uninitialized A::a
. Clang
немного лучше, поскольку он каким-то образом присваивает мусор (вместо удобного 0
) неинициализированным vars, так что вы видите их катастрофический эффект легче/раньше.
Мне не повезло в том, что вы заметили выше неинициализированный A::a
с помощью valgrind
; возможно, предложение, предлагающее valgrind
, может предоставить соответствующие варианты для определения этой ошибки.
Итог: большой вопрос, не очень надежные решения на данный момент... (как я его вижу).
Clang с clang-analysis может это сделать. Это событие создаст хороший HTML-отчет, который указывает, когда доступ к неиспользуемой переменной.
Рассмотрим следующий код
unint.cpp:
int main()
{
int a;
int b;
a++;
b = b + 5;
return 0;
}
Если код компилируется следующим комментарием, должны отображаться предупреждающие сообщения.
g++ -O3 -Wuninitialized unint.cpp
Примечание: для -Унициализации нужна опция -O3.