Получение предупреждения «контроль достигает конца действия функции, не являющейся недействительной», даже если я рассмотрел все случаи

#c

#c #многопоточность

Вопрос:

Почему, если у меня есть два условия, в то время как оба возвращают правильный тип в функции, как и должно быть, я получаю сигнал тревоги.

управление достигает конца функции, не являющейся недействительной [-Wreturn-type]

 bool EtherTrafGen::isGenerator()
{
    if (multipacket) return par("destAddresses").stringValue()[0];
    else if (!multipacket) return par("destAddress").stringValue()[0];
} 
 

Каков способ исправить такую тревогу?

Комментарии:

1. Просто используйте else вместо else if . Если только 2 выражения не ведут себя каким-то странным образом, что они на самом деле не противоположны. В этом случае также предоставьте else (и переосмыслите свой дизайн, чтобы он имел смысл для кого-то нового в проекте).

2. @BoBTFish На самом деле, в этом случае автору даже не нужно использовать else , поскольку поток управления завершит работу функции, если if условие выполнено

3. я думаю, что нет необходимости писать else if , потому что в if первой строке, если условие есть true , тогда else if оно будет false и vice verca

4. даже вам не нужно писать else слишком

5. Обнаружение того, что все пути покрыты, в общем случае является непростой задачей, вы должны помочь компилятору.

Ответ №1:

Даже несмотря на то, что контроль никогда не сможет достичь

 bool EtherTrafGen::isGenerator()
{
    if (multipacket) return par("destAddresses").stringValue()[0];
    else if (!multipacket) return par("destAddress").stringValue()[0];
    //here
} 
 

Компилятор не может этого знать (поскольку это an else if ), и он предупреждает вас о потенциальном неопределенном поведении, если оно достигнуто (возможно, другой поток изменяется multipacket после первой проверки и т. Д.). Вы можете просто добавить возвращаемое значение по умолчанию, чтобы удовлетворить компилятор:

 bool EtherTrafGen::isGenerator()
{
    if (multipacket) return par("destAddresses").stringValue()[0];
    else if (!multipacket) return par("destAddress").stringValue()[0];
    return false;
}
 

Или просто вырезать все целиком else if , так как это или true или false :

 bool EtherTrafGen::isGenerator()
{
    if (multipacket) return par("destAddresses").stringValue()[0];
    return par("destAddress").stringValue()[0]; // multipacket must be false here anyway
} 
 

Комментарии:

1. else здесь избыточно. просто верните

2. @MRB Хорошее наблюдение.

3. почему он не может добраться //сюда? У меня есть 2-й поток, который изменяет мультипакет между 2 проверками… и что теперь?

4. @UKMonkey Без этой предоставленной информации я просто делаю предположение, что у OP нет такого потока.

5. @Jarod42 В вопросе не указан тип мультипакета, так что, возможно, это std::atomic_bool . : P

Ответ №2:

Вы упускаете из виду один случай:

 bool EtherTrafGen::isGenerator()
{
    if (multipacket) return par("destAddresses").stringValue()[0];
    else {
        if (!multipacket) return par("destAddress").stringValue()[0];
        else ???? <---- what should be done here
    }
} 
 

Комментарии:

1. Вы упускаете из виду пункт OP: multipacket должен оцениваться true false только или

2. Вы правы, но он спросил, почему произошла эта ошибка, что означает, что он не видел, что случай не обрабатывается

3. Дело в том, что компилятор не обнаруживает, что обрабатываются все случаи (что может быть трудно обнаружить в общем случае).

Ответ №3:

Я начну с того, что способ, которым вы структурировали свое условие, довольно экзотичен. Вы должны просто записать это как:

 if (multipacket) doX()
else doY()
 

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

Однако ваш компилятор не настолько умен. Лучше не иметь предупреждения, чем иметь его и знать, что вы правы.


Если смотреть более широко, существует вероятность того, что приведенный выше код неверен, и дело не только в том, что компилятор недостаточно эффективен в своем анализе.

Если следующий код встречается в многопоточном контексте, у вас могут возникнуть редкие проблемы с потоками, когда при первом обращении к multipacket вы читаете false , что вынуждает вас перейти ко второй ветви, а при втором обращении вы читаете true, что вынуждает вас выйти из функции без какого-либо возвращаемого значения. Этот случай может произойти, если другой поток изменяет мультипакет между двумя его чтениями.

Конечно, это небольшая вероятность, так как даже если multipacket изменяется отдельным потоком, изменение может быть не сразу видно в этом методе, потому что значение находится в регистре / кэше / другом временном расположении, которое было введено компилятором.

Но зачем рисковать и писать неидиоматический код и получать предупреждение на руках?