2014-02-13 1 views
20

У меня есть код, подобный следующему:Как обойти «* ((пустота *) и б +4)» GCC может быть использован неинициализированным в этом предупреждении при использовании функции подталкивание :: опциональный

#include <boost/optional.hpp> 

::boost::optional<int> getitem(); 

int go(int nr) 
{ 
    boost::optional<int> a = getitem(); 
    boost::optional<int> b; 

    if (nr > 0) 
    b = nr; 

    if (a != b) 
    return 1; 

    return 0; 
} 

при компиляции с GCC 4.7.2 с Boost, 1.53, используя следующую команду:

г ++ -c -O2 -Wall -DNDEBUG

следующее предупреждение выдается:

13: 3: предупреждение: '((недействительными) & б +4)' может быть использовано неинициализированным в этой функции [-Wmaybe-неинициализированным]

Очевидно, что корень проблемы лежит GCC. См. GCC Bugzilla Кто-нибудь знает обходной путь?

+0

Если конструктор 'b' не инициализирует все, что находится внутри него , то, во всяком случае, 'b' в выражении' a! = b' может быть неинициализирован. Что делать, если вы фактически инициализируете 'b'? Вы все еще получаете предупреждение? – Shahbaz

+0

@Shahbaz: Конструктор 'b' создает необязательный параметр, где значение не существует. Это допустимое поведение для необязательного. 'a! = b' Должен быть прав, если оба варианта неинициализированы. Так что это должен быть правильный код. Инициализация 'b' значением отменяет предупреждение, но это не вариант, поскольку он изменяет поведение кода. Возвращение getitem() может быть неинициализированным необязательным. –

ответ

22

Есть два уровня неинициализированного анализа в НКУ:

  • -Wuninitialized: флаги переменные, которые безусловно использовали неинициализированные
  • -Wmaybe-uninitialized: флаги переменные, которые потенциально использовано неинициализированное

В gcc (*), -Wall включает оба уровня, хотя последний имеет ложные предупреждения, потому что анализ несовершенен. Пыльные предупреждения - это чума, поэтому самый простой способ избежать их - пройти -Wno-maybe-uninitialized (после -Wall).

Если вы все еще хотите получать предупреждения, но не можете вызвать сбои сборки (через -Werror), вы можете их перечислить с помощью -Wno-error=maybe-uninitialized.

(*) Clang не активирует -Wmaybe-uninitialized по умолчанию именно потому, что он очень неточен и имеет большое количество ложных срабатываний; Я желаю, чтобы gcc следил за этим руководством.

9

Я обнаружил, что изменения конструкции Ь в следующем (фактически равный) Код:

auto b = boost::make_optional(false,0); 

устраняет предупреждение. Однако следующий код (который также эффективно равен):

boost::optional<int> b(false,0); 

не устраняет предупреждение. Это все еще немного неудовлетворительное ...

+0

как насчет 'auto b = boost :: make_optional (false, 0);'? – rubenvb

+0

@ rubenvb: используя auto, я считаю, что это лучший стиль. Я изменю ответ. –

+0

У меня было то же предупреждение, но это решение мне не помогло. Я должен был избавиться от «факультативного» вообще (чего, к счастью, мог в моей ситуации). – Angew

4

Если бы тот же вопрос с этим фрагментом кода:

void MyClass::func(bool repaint, bool cond) 
{ 
    boost::optional<int> old = m_sizeLimit; // m_sizeLimit is a boost::optional<int> class attribute 

    if (cond) 
     m_sizeLimit = 60; 
    else 
     m_sizeLimit.reset(); 

    if (repaint) 
    { 
     if (old != m_sizeLimit) // warning here 
      doSomething(); 
    } 
} 

Не удалось избавиться от предупреждения с Paul Omta ответ, пытался написать:

boost::optional<int> old; 
if (m_sizeLimit) 
    old = boost::make_optional<int>(true, m_sizeLimit.value()); 
else 
    old = boost::make_optional<int>(false, 0); 

... без успеха ,

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

 #ifdef SDE_MOBILE 
     #pragma GCC diagnostic push 
     #pragma GCC diagnostic ignored "-Wmaybe-uninitialized" 
     #endif 

     if (old != m_sizeLimit) // warning here 
      doSomething(); 

     #ifdef SDE_MOBILE 
     #pragma GCC diagnostic pop 
     #endif 
+0

Спасибо за решение. Забежал в проблему с gcc 4.9.2, и ваше решение '# pragma' работало и было лучшим вариантом для меня. – mindriot

2

у меня был тип, который не легко построить так Бесполезный «Не хочу идти вперед: make_optional route. Назначение автоматической переменной с использованием возврата из функции обошло эту проблему для меня. Так что вы можете сделать:

boost::optional<Foo> Default() 
{ 
    return boost::none; 
} 

auto var(Default()); 

Это также будет работать как одна линия лямбда, так что вы можете просто сделать:

auto var([]()->boost::optional<Foo> { return boost::none; }()); 

 Смежные вопросы

  • Нет связанных вопросов^_^