Подтвердить что ты не робот

Легкий способ найти неинициализированные переменные-члены

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

Поиск их во время выполнения или времени компиляции в порядке.

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

4b9b3361

Ответ 1

Если вы используете 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++ невероятно полезен в улавливании множества распространенных ошибок С++.

Ответ 2

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

Ответ 3

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

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

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

Ответ 4

cppcheck найдет это.

Ответ 5

-Wuninitialized?

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

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

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

Ответ 6

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

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

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

Ответ 7

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

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

Ответ 9

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

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, может предоставить соответствующие варианты для определения этой ошибки.

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

Ответ 10

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

Ответ 11

Рассмотрим следующий код

unint.cpp:

int main()
{
    int a;
    int b;
    a++;
    b = b + 5;

    return 0;
}

Если код компилируется следующим комментарием, должны отображаться предупреждающие сообщения.

g++ -O3 -Wuninitialized unint.cpp

Примечание: для -Унициализации нужна опция -O3.