Простой способ найти неинициализированные переменные-члены - PullRequest
44 голосов
/ 20 января 2010

Я ищу простой способ найти неинициализированные переменные-члены класса.

Найти их в время выполнения или время компиляции в порядке.

В настоящее время у меня есть точка останова в конструкторе класса, и я проверяю переменные-члены по одной.

Ответы [ 11 ]

28 голосов
/ 26 мая 2010

Если вы используете 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++ также предупредит вас, когда переменная имеет правильный конструктор по умолчанию, и, следовательно, инициализация не потребуется. Он также предупредит вас, когда вы инициализируете переменную в конструкторе, но не в списке инициализации члена. И он предупреждает о многих других проблемах стиля C ++, таких как отсутствующие конструкторы копирования, поэтому вам может потребоваться немного очистить код, если вы хотите регулярно использовать -Weffc++.

Существует также ошибка, из-за которой он всегда выдает предупреждение при использовании анонимных союзов, которые в настоящее время нельзя обойти, кроме отключения предупреждения, что можно сделать с помощью:

#pragma GCC diagnostic ignored "-Weffc++"

В целом, однако, я обнаружил, что -Weffc++ невероятно полезен для выявления множества распространенных ошибок C ++.

10 голосов
/ 11 апреля 2011

cppcheck найдет это, например ::

cppcheck my_src_dir --output-file=check.txt --inconclusive --enable=warning
10 голосов
/ 20 января 2010

Valgrind ( FREE , в Linux) и Purify (в Windows) находят неинициализированные переменные, недействительные указатели и т. Д., Выполняя код вспециальная виртуальная машина.

Это простой в использовании и чрезвычайно мощный;он, вероятно, найдет много ошибок, помимо очевидных неинициализированных переменных.

Coverity , Klocwork и Lint могут найти неинициализированные переменные, используястатический анализ кода.

10 голосов
/ 20 января 2010

Valgrind может сказать вам, если вы используете Linux.

6 голосов
/ 20 января 2010

-Wuninitialized?

(Это только проверяет, используется ли переменная неинициализированным, т.е. если

struct Q { 
  int x, y;
  Q() : x(2) {}
  int get_xy() const { return x*y; }
};

g ++ будет предупреждать только тогда, когда пользователь вызывает get_xy() без присвоения y.)

5 голосов
/ 12 октября 2014

Visual Studio (MSVC) имеет параметр компилятора / sdl (Включить дополнительные проверки безопасности) (http://msdn.microsoft.com/en-us/library/jj161081.aspx). Во время выполнения он:

Выполняет инициализацию члена класса. Автоматическая инициализациячлены класса указателя типа равны нулю при создании объекта (до запуска конструктора). Это помогает предотвратить использование неинициализированных данных, связанных с членами класса, которые конструктор не инициализирует явным образом.

Это не поможетвы обнаруживаете неинициализированные переменные-члены во время компиляции, но это делает поведение более предсказуемым, когда это происходит во время выполнения. Хотя вы, конечно, не должны писать код, основанный на включении этой опции.

4 голосов
/ 20 января 2010

Если вы используете Visual Studio, вы можете скомпилировать в режиме отладки, остановить программу в отладчике и посмотреть, какие переменные инициализируются в байтах, содержащих 0xCC (стек) или 0xCD (куча).

Хотя лично я бы инвестировал в инструмент статического анализа для более тщательного подхода.

2 голосов
/ 20 января 2010

/ анализ в Visual Studio ("Система команд")

0 голосов
/ 11 июня 2016

Clang с помощью clang-analysis способен это сделать.Это событие создаст хороший отчет в формате HTML, который указывает, когда осуществляется доступ к неиспользуемой переменной

0 голосов
/ 21 июня 2013

Осторожно! Варианты компиляции, предложенные здесь, не являются ни надежными, ни независимыми от версии. Рассмотрим простой пример:

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) неинициализированным переменным, так что вы видите их катастрофический эффект легче / быстрее.

У меня не было особой удачи в обнаружении вышеупомянутого неинициализированного A::a с valgrind; возможно, предложение, предлагающее valgrind, могло бы предоставить подходящие варианты для выявления этой ошибки.

Итог: отличный вопрос, на данный момент не так много надежных решений ... (как я понимаю).

...