LINUX.ORG.RU

Это вообще законно? Провал выполнения в нижележащую «мёртвую» функцию

 , , , ,


3

3

Случай из реального проекта, код ~10-летней выдержки. Когда-то давно забыл добавить return в функцию, где имеется хитрая условная компиляция. Долгое время всё нормально работало, а сегодня вот пересобрал проект и поимел весёлых проблем. При проигрывании звука сегфолтилось, хотя вроде как в коде всё было нормально. Старые версии (собранные старым GCC) не сегфолтились. При отключенной оптимизации сегфолта тоже не было. Что тут можно ещё сказать? Спасибо Сталлману за gdb, сильно удивился когда увидел вызов якобы вырезанной функции в нём. Ну и главное: читайте и анализируйте Warning’и, господа! Минимальный пример:

$ cat dead_code.cpp 
// dead_code.cpp

#include <cstdio>

int stub_0();
int pxt_PlayWithCallback(int chan, int slot, char loop, void (*FinishedCB)(int, int));

int pxt_Play(int chan, int slot, char loop) {
#ifdef _PLS_NO_DEAD_CODE
	if (stub_0()) {
		fprintf(stderr, "!!!!! GOOD CODE !!!!!\n");
	}
#else
    return pxt_PlayWithCallback(chan, slot, loop, NULL);
#endif
}

int pxt_PlayWithCallback(int chan, int slot, char loop, void (*FinishedCB)(int, int)) {
	fprintf(stderr, "????? DEAD CODE ?????\n");
	return stub_0();
}

int stub_0() { return 42; }

int main(int argc, char *argv[]) {
	return pxt_Play(-1, 20, 0);
}

// OK:
$ g++ dead_code.cpp
$ ./a.out 
????? DEAD CODE ?????

// OK:
$ g++ -D_PLS_NO_DEAD_CODE dead_code.cpp
$ ./a.out 
!!!!! GOOD CODE !!!!!

// WTF?:
$ g++ -O2 -D_PLS_NO_DEAD_CODE dead_code.cpp
$ ./a.out 
!!!!! GOOD CODE !!!!!
????? DEAD CODE ?????
Segmentation fault (core dumped)

// WTF???:
$ g++ -O3 -D_PLS_NO_DEAD_CODE dead_code.cpp
$ ./a.out 
!!!!! GOOD CODE !!!!!
!!!!! GOOD CODE !!!!!
...
!!!!! GOOD CODE !!!!!
!!!!! GOOD CODE !!!!!
Segmentation fault (core dumped)

А ведь довольно интересный простор за этим может скрываться. Ну право ведь, забыли return проставить, компилятор же по-дефолту return 0 впихнёт, верно? А я в этом был уверен.

P.S.

// Имеется предупреждение по-дефолту, отсутствует ret в конце функции, провал и сегфолт.
$ gcc --version
gcc (GCC) 10.2.1 20200723 (Red Hat 10.2.1-1)

// Предупреждение только с -Wall, ret в конце функции имеется, нет провала и сегфолта.
$ gcc --version
gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-39)

P.P.S. поиграться с компиляторами:

C++: https://gcc.godbolt.org/z/7ne8PM
C: https://gcc.godbolt.org/z/b6vqbK

Может кто-нибудь из профи подробно объяснить механизм такого поведения? Спасибо.

См. комментарии и ссылки в теме.

★★★★★

Последнее исправление: EXL (всего исправлений: 4)

Ответ на: комментарий от byko3y

В языках с поддержкой сильных типов есть проверка границ в рантайме

И сразу же +тормоза и потенциальная уязвимость в DoS-у. Нет, проверка только в debug-е не поможет, ибо 100% тестовое покрытие по входным данным невозможно, а отсутствие проверок в release сборках возвращает «проблемы» c/c++(переполнения - арифметические и буферов).

Для этого в крестах ввели поддержку ссылок

Очвидно, речь о случаях, когда указатель может быть null. { type* p{}; switch (some) { case 1: p = ...; case 2: p = ...; ... } if (!p) return; f1(*p); f2(*p); ... }. Отсутствие в си ссылок роли не играет.

Правильное предупреждение

Лол. Нет, оно не правильное, ибо появляется та самая «куча варнингов».

Неправильное предупреждение. Хз, откуда его взяли

Почитай тот тред целиком, там много мыслей, подобных твоим.

абсолютное зло, нет никакого оправдания его существованию

А вот не отказывался бы попробовать написать std::deque - знал бы, зачем оно нужно.

Опять ссылкопроблемы

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

Итого: опять аппеляция к хэлвордам.

anonymous
()
Ответ на: комментарий от fsb4000

а я не про аналогию ключей. Microsoft STL собирается двумя компиляторами в CI, если любой из компиляторов выдаст предупреждение/ошибку то тесты не пройдут

Ну я их поздравляю, чо, заморочились. Но если контора выделяет ограниченные ресурсы на проект или проект тупо большой, то на такие вещи приходится не обращать внимание. Я тебе могу показать людей, которые требуют, чтобы код из репозитория не выдавал ошибки линтов. Это что-то типа «у вас тут 3 пробела вместо 4, мы не соберем ваш код». И это правила выполняются, а дедлайны пролюбливаются.

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

И сразу же +тормоза и потенциальная уязвимость в DoS-у. Нет, проверка только в debug-е не поможет, ибо 100% тестовое покрытие по входным данным невозможно, а отсутствие проверок в release сборках возвращает «проблемы» c/c++(переполнения - арифметические и буферов)

Да, конечно же, удаленное выполнение кода более приемлимо, чем падение в корку с фиксацией конкретной ошибки.

Очвидно, речь о случаях, когда указатель может быть null. { type* p{}; switch (some) { case 1: p = ...; case 2: p = ...; ... } if (!p) return; f1(*p); f2(*p); ... }. Отсутствие в си ссылок роли не играет

Не совсем понимаю, о чем пример. Если где-то действительно нужно использовать указатель — используй его. Я пишу лишь о том, что в Си часто используют указатель в роли ссылки, и именно этой семантикой по умолчанию компиляторы Си наделяют указатели, при этом настоящие указатели в C\C++ можно использовать только через «volatile».

Лол. Нет, оно не правильное, ибо появляется та самая «куча варнингов»

Но именно так и работают нынешние компиляторы.

Почитай тот тред целиком, там много мыслей, подобных твоим

Я засну.

Без указателей и ссылок не получится писать быстрый и не жрущий код

Еще раз: я за ссылки и против указателей. То, что обычно применяется как указатель, на самом деле является ссылкой, которая не может быть NULL.

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

Это что-то типа «у вас тут 3 пробела вместо 4, мы не соберем ваш код»

clang-format вызывается для каждых файлов .c .cpp .h .hpp

Можно в CI добавить проверку чтобы проверял что clang-format не меняет файл и выдавать ошибку если перед коммитом забыли сделать clang-format.

Проблема лишь в начальной организации. Дальше это не требует времени, так как почти всё можно автоматизировать.

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

[code]$ ./a.out !!!!! GOOD CODE !!!!! $ gcc –version gcc (Debian 10.2.0-7) 10.2.0[/code]

всегда нужно использовать -Wall -Wextra и стремиться к нулевому количеству ворнингов

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

Да, конечно же, удаленное выполнение кода более приемлимо, чем падение в корку с фиксацией конкретной ошибки.

Нет, конечно, это чушь собачья. Шило на мыло - вот такая характеристика подходит. Как видно, смысла в повсеместных проверках в рантайме нет.

Если где-то действительно нужно использовать указатель — используй его.

Тогда либо UB, либо NullPointerException, либо куча ворнингов(мусорных, буквально). Опять нормального решения нет.

Я пишу лишь о том, что в Си часто используют указатель в роли ссылки, и именно этой семантикой по умолчанию компиляторы Си наделяют указатели, при этом настоящие указатели в C\C++ можно использовать только через «volatile».

Да, указатель = ссылка + null pointer value. Очевидно, null value нужен(нужность std::optional никто не отрицает, вроде). Также очевидно, никто не будет сознательно разименовывать null. Либо я не понял твою мысль.

Но именно так и работают нынешние компиляторы.

Нет.

Я засну.

Тогда остаётся верить в серебрянные пули и недоумевать, почему существующие решения так плохи. При таком подходе едва ли можно чем-то помочь.

Еще раз: я за ссылки и против указателей. То, что обычно применяется как указатель, на самом деле является ссылкой, которая не может быть NULL.

Э… Пример, пожалуйста. Поскольку указатель - это(в первом приюлижении) именно что ссылка, которая может быть null.

anonymous
()
Ответ на: комментарий от byko3y

Короче ты за то, чтобы компилятор запрещал компилировать такой код (non-void функцию без return вконце), правильно? А что тогда делать при следующей логике: есть функция и ряд if-проверок (или switch-case-проверок). В случае совпадения одной из проверок происходит возврат (т.е. вызов return) соответствующего значения. А в случае если ничего не совпало будет брошено исключение, т.е. в самом конце функции. Т.е. здесь return в конце функции после throw никогда не будет вызван, но при его отсутствии код не будет компилироваться (представим, что так было бы). Но ведь здесь явно этот последний return лишний.

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

А как cl.exe из состава Visual Studio решает эту проблему?

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

https://en.cppreference.com/w/cpp/language/attributes/noreturn

https://gcc.godbolt.org/z/YrahEb

компилятор проверяет, что либо в функции есть return либо произошёл вызов функции помеченной [[noreturn]] `

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

В Обероне компилятор вставляет герерацию исключения если функция не вызвала RETURN. Сразу видно, что проектировали безопасный язык

Если бы проектировали «безопасный язык», то это было бы ошибкой компиляции.

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

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

Кстати, а чего вы под центось чё нить пободрее не завёзёте себе? Можно же ту же версию abi настроить, но санитайзинг и прочее в том же gcc - на порядок лучше будет в 9.х, чем в 4.х и даже 5.х.

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

Имеет полное право, потому что UB

UB будет если использовать возвращённое значение. Но сам возврат обязателен. Чё то они тут горбатого лепят. Или в каком стандарте написано, что можно не возвращаться?

no-such-file ★★★★★
()
Ответ на: комментарий от byko3y

Если реализации компиляторов Си писали хакеры, индусы-хакеры, но хакеры

Я тебе открою секрет: все две открытые реализации C сейчас написаны на C++.

Вообще, как показывает практика, если заменить слово «хакер» с подобных высказываниях на «самоуверенный долбодятел», смысл вообще никак не меняется.

hateyoufeel ★★★★★
()
Последнее исправление: hateyoufeel (всего исправлений: 1)
Ответ на: комментарий от no-such-file

UB будет если использовать возвращённое значение.

Это в C. В C++ UB будет в конце выполнения кода функции. Подробнее см. обсуждение разработчиков GCC, в частности этот комментарий:

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94768#c5

Note C and C++ have slightly different notice about «no return statement in function returning non-void»; In C it is only undefined if the return value is used while in C++ it is undefined the moment that the end of the function happens.

EXL ★★★★★
() автор топика
Ответ на: комментарий от no-such-file

UB будет если использовать возвращённое значение.

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

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

ошибка компиляции, так как такую функцию мы не можем пометить [[noreturn]]

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

Правда MSVC вставляет генерацию прерывания int 3, так что код на этом UB упадёт.

https://gcc.godbolt.org/z/fs6E1h

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

Блин ну не томи душу, дай знать чего почитать, может грамотный сет доки где-то за душой держишь, что бы разобраться как оно сейчас, что бы поскорее мою тупую тупость хотя бы немного приуменьшить.

Нет, int будет в eax

Это где то можно вычитать? Я может натупил с stdcall, там вроде всегда в eax возвращается, да. Но про типы я был уверен, что в соглашениях о вызовах не особо упоминается, максимум про размеры значений.

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

Нет, конечно, это чушь собачья. Шило на мыло - вот такая характеристика подходит. Как видно, смысла в повсеместных проверках в рантайме нет

Да, поэтому примерно половина всех уязвимостей в софте — это тихо переполняющиеся буферы/стэки. Люди ругают питон за то, что тот кидается стэками — а по-твоему тихо портящая данные и падающая программа лучше?

Тогда либо UB, либо NullPointerException, либо куча ворнингов(мусорных, буквально). Опять нормального решения нет

Опасную работу с указателями можно локализовать до единственного преобразования типов, явного и потом не требующего никаких предупреждений. Тот же Rust провоцирует именно такой код. Вместо этого Си провоцирует размазывание опасных операций по всему коду. Хуже того, эффективных способов делать полиморфные функции в Си нету, что провоцирует написание рантайм диспетчеризации, которой, как правило, усыпан любой сишный код солидных размеров.

Я пишу лишь о том, что в Си часто используют указатель в роли ссылки, и именно этой семантикой по умолчанию компиляторы Си наделяют указатели, при этом настоящие указатели в C\C++ можно использовать только через «volatile».

Да, указатель = ссылка + null pointer value. Очевидно, null value нужен(нужность std::optional никто не отрицает, вроде). Также очевидно, никто не будет сознательно разименовывать null. Либо я не понял твою мысль

Указатель не является ссылкой, потому что данные по указателю неподконтрольны коду. Они могут быть изменены ОС-ью, другим потоком, вызовом функции в этом же потоке. То есть, это ссылка на неподконтрольные нам данные. Если данные подконтрольны нам, мы знаем их размер и контролируем область жизни, то указатель становится ссылкой и теряет возможность быть NULL. Это то, как указатели и ссылки реализованы в паскале, к слову. Да и в Rust тоже. То есть, в языках, где типы данных сделаны не с целью «отстаньте от нас уже».

Но именно так и работают нынешние компиляторы.

Нет

А как? Делаешь "-Wall" в небрежно писанном коде, и получаешь стенку предупреждений о неиспользованных переменных.

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

Т.е. здесь return в конце функции после throw никогда не будет вызван, но при его отсутствии код не будет компилироваться (представим, что так было бы). Но ведь здесь явно этот последний return лишний

Додики из комитета сами пришли к такому положению. Да, писать return везде, даже если он не нужен — стандарт не оставляет вариантов. Выше указали на особенность работы MSVC, у которого есть noreturn функции, после которых таки можно не писать return, что чутка упрощает задачу, но является нестандартным решением, а значит непортируемо.

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

А если функция может может как возвратить управление, так и нет возвратить в зависимости от ряда причин?

Тогда писать return.

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

Часто ловюсь на этой истории, но тесты такое ловят ну супер быстро

Тесты здесь никак не помогают. Фича работала годами исправно, пока внезапно не...

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

На сайте - доктор довольно сильно лечит. А так вообще - это сценический псевдоним или злой туман реально всё так чётко покрыл?

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

Я тебе открою секрет: все две открытые реализации C сейчас написаны на C++

В GCC используется куча языков, не только C/C++. На крестах там написаны libstdc++, libsanitizer, а также go, d, и либы к ним. Статистика для 10.2.0 такая:

*.c: 150 Мб, 120 тыс файлов
*.adb+*.ads+*.ada: 50 Мб, 12 тыс файлов
*.go: 28 Мб, 8 тыс файлов
*.cc: 25 Мб, 16 тыс файлов
*.d: 20 Мб, 6 тыс файлов

Вообще, как показывает практика, если заменить слово «хакер» с подобных высказываниях на «самоуверенный долбодятел», смысл вообще никак не меняется

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

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

В чём фича? Тесты которые хоть как-то проверяют возвращаемое значение прямо берут и падают

Знал бы куда упаду — соломку подстелил. Обложить все параметры будет более трудоемко, чем в тупую отладить код. Может быть твой тест не проверит код, а может ты напишешь специально проверку, и она вообще никогда ни одной ошибки не обнаружит, потому что не повезет.

byko3y ★★★★
()
Ответ на: комментарий от no-such-file

Что они там курят в комитете по крестам?

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

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

И последующий выход за пределы этой функции дают в сумме неопределенное поведение

Зачем именно такое поведение внесено в стандарт. Особенно если учесть, что в стандарте Си другое?

no-such-file ★★★★★
()
Ответ на: комментарий от byko3y

Да, поэтому примерно половина всех уязвимостей в софте — это тихо переполняющиеся буферы/стэки.

Ну да. С проверками в рантайме половина уязвимостей будет «маршрутизатор ложится на 3.5 пакетах в секунду». И?

Люди ругают питон за то, что тот кидается стэками — а по-твоему тихо портящая данные и падающая программа лучше?

Тебя снова понесло мимо темы. Даже не буду спрашивать, как как ты умудрился сравнить стэктрейсы в лицо пользователю(падение скрипта на питон) и бессимптомную порчу данных(НЕ упавшую прогу на c/c++). Это лол.

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

Нельзя, очевидно. Я ж говорю - тебе просто знаний не достаёт, вот ты и веришь во всякие байки про «можно». За это время мог бы уже попробовать написать, что я тебе предлагал, и убедиться сам.

Указатель не является ссылкой, потому что данные по указателю неподконтрольны коду. Они могут быть изменены ОС-ью, другим потоком, вызовом функции в этом же потоке. То есть, это ссылка на неподконтрольные нам данные. Если данные подконтрольны нам, мы знаем их размер и контролируем область жизни, то указатель становится ссылкой и теряет возможность быть NULL. Это то, как указатели и ссылки реализованы в паскале, к слову. Да и в Rust тоже. То есть, в языках, где типы данных сделаны не с целью «отстаньте от нас уже».

Данные по ссылке тоже «неподконтрольны коду», точно так же могут быть изменены «ОС-ью, другим потоком, вызовом функции в этом же потоке». Начинаю верить фразе «я до сих пор так и не изучил кресты» в буквальном смысле и посмеиваться над «с крестами меня рыночек оторвал бы с руками».

А как? Делаешь «-Wall» в небрежно писанном коде, и получаешь стенку предупреждений о неиспользованных переменных

Во-первых, я не знаю, зачем ты делаешь столько неиспользуемых переменных. Во-вторых, неиспользуемые переменные к UB(а именно о нём речь, если ты забыл) имеют малое отношение.

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

Блин ну не томи душу, дай знать чего почитать, может грамотный сет доки где-то за душой держишь, что бы разобраться как оно сейчас, что бы поскорее мою тупую тупость хотя бы немного приуменьшить

google: calling convensions

Далее архитектура: x86, x64, arm, etc. Соглашения вполне себе общеприняты.

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

Выше же написали

Написали почему такой код должен компилироваться. Я и не возражаю. Но почему такой код должен вывалиться из функции я решительно не понимаю. В чём сакральный смысл требовать UB сразу вместо ret и потом UB?

no-such-file ★★★★★
()
Последнее исправление: no-such-file (всего исправлений: 2)
Ответ на: комментарий от byko3y

Статистика для 10.2.0 такая:

Ммм, кажется ты ещё не знаешь самой мякотки GCC. У них C++-код в файлах с расширением *.c, берём почти любой *.c файл кодовой базы, открываем:

https://gcc.gnu.org/git/?p=gcc.git;a=blob;f=gcc/passes.c;h=6ff31ec37d7fd9f21bfa49a3102c112cebd0cbe0;hb=HEAD

Ctrl+F "class"
Ctrl+F "namespace"

GCC восхитителен.

EXL ★★★★★
() автор топика
Последнее исправление: EXL (всего исправлений: 1)
Ответ на: комментарий от no-such-file

@byko3y всё правильно написал, вот там ответ разрабов

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94768#c1

This is a valid C++ program and it would be non-conforming to reject it. The compiler can’t even assume the program has undefined behaviour, because g(int) could throw an exception, or do something that terminates, or simply never return (e.g. go into an infinite loops with side effects like I/O).

потом тип который баг открыл написал

Surprising. The standard looks broken to me. Standards conformance only really matters if GNU C++ is in standards conformance mode.

Most of the time, it is in its own GNU mode and so could do a more useful job here rather than IMHO blindly following non-useful standards.

и последний ответ

Nobody is «blindly following» anything. It’s been discussed in detail by people who know what they’re talking about, over many years (including again when -Wreturn-type was enabled by default for C++). Rejecting valid C++ code by default is not OK.

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

И как это отвечает на вопрос, почему UB должен быть сразу, а не после возврата как в СИ?

Кстати, отдельный вопрос - а что это UB в GCC таки по-разному возникает с C и в C++?

no-such-file ★★★★★
()
Последнее исправление: no-such-file (всего исправлений: 1)
Ответ на: комментарий от anonymous

Ну да. С проверками в рантайме половина уязвимостей будет «маршрутизатор ложится на 3.5 пакетах в секунду». И?

Ты сильно преувеличиваешь стоимость проверок. Основные тормоза на современных x86 и arm берутся от неугаданных условных переходов и кэш мисов, а не от операций в регистрах, которыми обычно реализовываются эти самые проверки в рантайме. Я не помню, что там по флагам, но по-моему на обоих архитектурах есть флаг переполнения после арифметики, то есть, проверка переполнения вообще простейше реализуется на уровне машинных кодов и не занимает кэш.

Тебя снова понесло мимо темы. Даже не буду спрашивать, как как ты умудрился сравнить стэктрейсы в лицо пользователю(падение скрипта на питон) и бессимптомную порчу данных(НЕ упавшую прогу на c/c++). Это лол

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

Я ж говорю - тебе просто знаний не достаёт, вот ты и веришь во всякие байки про «можно». За это время мог бы уже попробовать написать, что я тебе предлагал, и убедиться сам

Каких еще знаний? Я тебе пишу про воображаемый язык, которым должен был бы быть Си — ты можешь читать мои мысли? Может расскажешь тогда мне сразу, насколько реально мой воображаемый язык реализовать?

Данные по ссылке тоже «неподконтрольны коду», точно так же могут быть изменены «ОС-ью, другим потоком, вызовом функции в этом же потоке»

Для этого они должны стать указателем, потому что в противном случае весь доступ к ним находится под контролем и формально у этих данных нет адреса. То есть, ссылка не передает адрес ячейки в функцию — ссылка на уровне синтаксиса связывает ячейку формального параметра с ячейкой фактического параметра, будь то некий регистр, стэк, или память из кучи. Возврат указателя на такую ссылку — это предупреждение или ошибка, примерно как это и трактует Rust.

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

Самое смешное то, что даже Free Pascal, в котором крайне мало оптимизаций, умеет в контроль указателей, засовывая локальные переменные в регистры, но выкидывая их в оперативу, если кто-то берет адрес переменной. А Си не может, из-за фундаментального изъяна архитектуры компилятора.

Во-первых, я не знаю, зачем ты делаешь столько неиспользуемых переменных. Во-вторых, неиспользуемые переменные к UB(а именно о нём речь, если ты забыл) имеют малое отношение

Ты односложно отвечаешь. Ты хоть сам помнишь, о чем изначально был разговор?

byko3y ★★★★
()
Последнее исправление: byko3y (всего исправлений: 1)
Ответ на: комментарий от no-such-file

Написали почему такой код должен компилироваться. Я и не возражаю. Но почему такой код должен вывалиться из функции я решительно не понимаю. В чём сакральный смысл требовать UB сразу вместо ret и потом UB?

Потому что это не просто ret, но еще и выход из блока обработки исключений. ret — это один байт, в вот выход из блока исключений — это уже несколько байт вдобавок к самому ret. Нанооптимизиторы решили включить смекалку, получив таким образом более компактный код, который лучше влазит в L1i кэш, увеличивая производительность выполнения в среднем на 0.3%. Это ж в мировом масштабе представь сколько сэкономленного электричества! Каждый запускает FF/Chrome, и они на 0.3% эффективнее работают.

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

Ты сильно преувеличиваешь стоимость проверок

Нет. Производительности уже не хватает, даже без них. Особенно мобильных сетей касается, где хоть сколько-нибудь нормальный протекшн не сделать в принципе.

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

Сказал же, мимо.

Я тебе пишу про воображаемый язык, которым должен был бы быть Си — ты можешь читать мои мысли?

Так бы сразу и сказал…

Может расскажешь тогда мне сразу, насколько реально мой воображаемый язык реализовать?

Уже расказал - реальность 0%.

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

Ну и бредятина.

Ты хоть сам помнишь, о чем изначально был разговор?

Конечно помню:

UB — это ошибка, и должна быть ошибкой [компиляции]

Это вообще законно? Провал выполнения в нижележащую «мёртвую» функцию (комментарий)

anonymous
()
Ответ на: комментарий от anonymous

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

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

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

Ну и бредятина

Ну что мне сказать... Rust писали лошары. На этом и разойдемся.

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

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

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

Rust писали лошары.

ЧСХ, в здесь ты прав.

На этом и разойдемся.

ok.

anonymous
()
Ответ на: комментарий от no-such-file

почему UB должен быть сразу, а не после возврата как в СИ?

Может потому что в C++ есть деструкторы и значение соответствующих типов всегда «используется», м?

anonymous
()
Ответ на: комментарий от byko3y

Адекватный компилятор, к которым GCC не относится…

MSVC нынче — это единственный годный компилятор…

Убейся об стену.

MSVC вообще может зацикливаться при /Ob2 и т.д.

anonymous
()
Ответ на: комментарий от byko3y

Я тебе могу показать людей, которые требуют, чтобы код из репозитория не выдавал ошибки линтов. Это что-то типа «у вас тут 3 пробела вместо 4, мы не соберем ваш код». И это правила выполняются, а дедлайны пролюбливаются.

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

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