#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 изменяется отдельным потоком, изменение может быть не сразу видно в этом методе, потому что значение находится в регистре / кэше / другом временном расположении, которое было введено компилятором.
Но зачем рисковать и писать неидиоматический код и получать предупреждение на руках?