LINUX.ORG.RU
ФорумTalks

С++ имеет синтаксис для некорректных функций

 


0

2

В С++ (даже 17) можно не писать return в функции, которая должна что-то возвращать. Это скомпилируется. Но в рантайме, при вызове этого метода прога упадет с кодом ошибки.

То есть, имеется специальный синтаксис для функций, про которые заранее на этапе компиляции известно, что они некорректные. Может ли здоровый человек такое придумать?

Вы там охренели? Это вообще нормально? Алло, не бросайте трубку.

★★★★☆

c++/c-синтаксис вообще хуже всх, как будто его специально дизайнили что бы проще было лепить ошибки и сложно читать.

thunar ★★★★★
()

Это вообще нормально?

Не отличать синтаксис от семантики? Для жавистов может и нормально.

заранее на этапе компиляции известно, что они некорректные

Нет. UB наступит только если управление дойдёт до конца такой функции, чего может и не произойти.

xaizek ★★★★★
()

Вы там охренели? Это вообще нормально? Алло, не бросайте трубку.

Продолжай бомбить, стиви

Manhunt ★★★★★
()

Но в рантайме, при вызове этого метода прога упадет с кодом ошибки.

Врёшь ты всё, будет UB.

pon4ik ★★★★★
()
Ответ на: комментарий от xwicked

QtCreator + GNU C++ - не компилируется без return... Default.

Значит всё же не дефолт

fornlr ★★★★★
()

Тут требуется присутствие Iron_Bug. Она наверняка объяснит почему это правильно и вообще, жабакодирам не понять божественного C++.

hateyoufeel ★★★★★
()
Последнее исправление: hateyoufeel (всего исправлений: 1)

Бывают интересные ситуации. Одна версия GCC выдавала предупреждение, если в функции в конце нет return, хотя туда управление никогда не доходит — switch-case покрывал все случаи. А другая выдавала предупреждение, если в конце есть return. Потому что туда управление никогда не доходит. Особенно весело было, когда сборка была всегда с -Werror.

i-rinat ★★★★★
()
Ответ на: комментарий от i-rinat

Особенно весело было, когда сборка была всегда с -Werror.

Мне казалось, что все уже усвоили — -Werror в сборке только на билд-сервере со стабильным тулчейном же.

kirk_johnson ★☆
()
Ответ на: комментарий от RazrFalcon

Поэтому и сделали Rust.

В итоге в Rust запили юникодные имена :)

kirk_johnson ★☆
()

В С++ (даже 17) можно не писать return в функции, которая должна что-то возвращать. Это скомпилируется. Но в рантайме, при вызове этого метода прога упадет с кодом ошибки.

Нет. Функция не обязательно упадёт. Более того, она даже может выдавать* правильный (ожидаемый) результат. Курите ссылку https://en.m.wikipedia.org/wiki/X86_calling_conventions, кому интересно.

*Но это всё равно будет UB

Crocodoom ★★★★★
()

То есть, имеется специальный синтаксис для функций, про которые заранее на этапе компиляции известно, что они некорректные

Вообще говоря, условные ретурны могут быть где-то выше в теле функции, и компилятор не обязан (и не может) проверять, что хотя бы один из этих условных ретурнов всегда выстрелит. Только в простых случаях.

Crocodoom ★★★★★
()

То есть, имеется специальный синтаксис для функций, про которые заранее на этапе компиляции известно, что они некорректные. Может ли здоровый человек такое придумать?

C++ (как и Си) допускает вставки на ассемблере. Можно вручную перед return запихнуть в стек значение или адрес для него и это будет нормально работать. Конечно, «грязный хак», но тем не менее язык их позволяет и некоторым даже нравится. В каких-то случаях может даже такое нужно, например, если с железом напрямую общаться или системные какие-то хаки.

praseodim ★★★★★
()
Ответ на: комментарий от xaizek

чего может и не произойти.

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

легко можно сгенерить функцию, в которой контролфлоу дойдет до этого места

с какого лешего это UB то? Что ты тут собрался оптимизировать через UB? Кто-то серьезно собирается полунерабочими функциями?

проклятые наркоманы, обколются своими веществами и гадят в Стандарт ересь

stevejobs ★★★★☆
() автор топика
Ответ на: комментарий от kirk_johnson

откуда ж вы лезете то!

у разных компиляторов разыное понимание, что такое ошибка и ворнинг

у меня сейчас GCC 8.2.0, а у половины софта код написан еще во времена какой-нибудь некрофилии вроде 4.9.1, и на практике почти всегда первое что ты делаешь - начинаешь писать пачки патчей, которые ищут и выкашивают все эти -Wall, -Werror. А до этого нужно потратить кукуево время, чтобы загрепать все эти окаменелые автотулзы и найти эти флаги для выкорячивания

разные флаги могут действительно интерпретироваться по-разному, но -Wall -Werror это та комбинация, которая к проблемам приводит в 146% случаев

stevejobs ★★★★☆
() автор топика
Последнее исправление: stevejobs (всего исправлений: 1)
Ответ на: комментарий от stevejobs

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

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

Crocodoom ★★★★★
()
Ответ на: комментарий от stevejobs

Какую фичу конкретно выпилить? Запретить функции без ретурна в конце, или же запретить множественные ретурны вовсе?

Crocodoom ★★★★★
()
Ответ на: комментарий от stevejobs

и если случится - выбросить ошибку еще на этапе компиляции

Он может выдать предупреждение. Требование ошибки приведёт к ложным срабатываниям, которые допустимы для предупреждений, но не ошибок.

с какого лешего это UB то? Что ты тут собрался оптимизировать через UB?

UB существует не для оптимизаций, хоть и может использоваться для целей оптимизации.

Кто-то серьезно собирается полунерабочими функциями?

ComplexObject
function(int a)
{
    if (a > 0) {
        // do a lot of work
        return ComplexObject();
    }
    dumpLogAndLeave();
}

Вполне рабочий (отфонарный примитивный) код и return после dumpLogAndLeave() ему не нужен. Но на практике компилятору намекают о недостижимости, чтобы предупреждения не сыпались.

xaizek ★★★★★
()
Ответ на: комментарий от stevejobs

-Wall -Werror это та комбинация, которая к проблемам приводит в 146% случае

А у Nginx тем временем -Wall -Wextra -Werror.

i-rinat ★★★★★
()
Ответ на: комментарий от xaizek

Ваш пример хороший. Более того, у ComplexObject может просто не быть дефолтного конструктора, и тогда осмысленный объект этого типа просто невозможно создать после вызова dumpLogAndLeave, поскольку нужные аргументы для конструктора банально отсутствуют в скоупе.

Crocodoom ★★★★★
()
Ответ на: комментарий от stevejobs

на практике почти всегда первое что ты делаешь - начинаешь писать пачки патчей, которые ищут и выкашивают все эти -Wall, -Werror

Стиви, пиши на Яве. Пожалуйста.

tailgunner ★★★★★
()
Ответ на: комментарий от vtVitus

наличие нескольких исключений всего лишь подтверждает общее правило.

Если объявления функций могут работать иначе, то почему выходы из функций не могут?

int echo ();

int main ()
{
    return echo (42);
}

int echo (int i)
{
    return i;
}

Darth_Revan ★★★★★
()
Последнее исправление: Darth_Revan (всего исправлений: 1)
Ответ на: комментарий от RazrFalcon

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

1) Может быть сложное ветвление с участием вызовов функций, даже неизвестных в текущем модуле

2) Могут быть простые ветвления, и компилятор скажет типа «вы не сделал return в случае, когда x < 0», но где-то выше по коду (вне функции) уже проверено это условие.

Тут получается, что гарантией «корректной» работы функции уже является не компилятор, а программист. Который знает больше компилятора. Но который также может и ошибаться. Это C++ :-)

Crocodoom ★★★★★
()
Ответ на: комментарий от i-rinat

надо было #ifdef делать, и в зависимости от версии компилятора вставлять или не вставлять return в конце! :)

Harald ★★★★★
()
Ответ на: комментарий от RazrFalcon

в Rust return обязателен. Если очень надо - есть спец сигнатура.

То есть они закрепили best practice в компиляторе, и добавили обходной вариант, когда от этого best practice всё же нужно отступать. Это ОК, это правильно.

Crocodoom ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.