LINUX.ORG.RU

Навеяно свежей дырой в Xorg

 , ,


9

7

Привет, ЛОР!

Ты, наверное, уже видел свежую дыру в Xorg, патч для которой выглядит буквально вот так:

-        else
+        else {
             free(to->button->xkb_acts);
+            to->button->xkb_acts = NULL;
+        }

В связи с этим у меня возник вопрос: а почему в стандартной библиотеке C нет макроса SAFE_FREE()?

#define SAFE_FREE(ptr) do{free(ptr);(ptr)=NULL;}while(0)

Напомню, что значение указателя после вызова free() является неопределённым согласно стандарту. Не только значение памяти, на которое он указывает, но и значение самого указателя, и работа с ним представляет собой жуткое undefined behaviour, а значит единственное что можно сделать – занулить его.

Так вот, почему даже таких банальных вещей нет? Я уже не говорю про строковый тип, а то даже Эдичка тут строки не осилил.

Моя гипотеза тут: C – это язык культа страданий во имя страданий.

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

именно значение самого указателя?

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

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

популярными эти архитектуры не стали, в народ не пошли, но свой след оставили, намертво вписав свои особенности в стандарт С )

распечатать значение указателя, содержащее trap representation тем не менее можно, преобразовав его к unsigned char * и распечатав каждый символ из этого массива - это практически официальный способ вывода на печать всего, чего печатать нельзя ) но увы - нет никаких гарантий, что данная конкретная имплементация printf делает максимум возможного для того, чтобы не встрять. в большинстве printf реализаций для печати указателей рулит железобетонное (uintptr_t)(void*)ptr, хотя наличие uintptr_t стандартом не гарантируется, он опциональный. и тем не менее. такие дела.

итого - живых архитектур таких нет, компиляторов нет, а стандарт есть ). поэтому gcc говорит - «ничо не знаю, все будет по стандарту», а cmake кладет болт и предлагает использовать это правило только в параноидальном режиме.

в товарищах согласья нет )

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

Пользователи каких ЯП читают стандарты этих ЯП? Кто-то кроме сишников вообще в курсе, что у ЯП есть какой-то там стандарт?

Ты от нечего делать нашел книжечку потоньше про айти и теперь хвалишься, что ее осилил? Почитал бы хотябы стандарт C++ или JVM, зауважали бы.

А пока, стандарты языков нужны только разработчикам компиляторов для этих языков. Обычным юзерам хватит официальной документации по типу K&R.

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

Пользователи каких ЯП читают стандарты этих ЯП?

Тех, у которых эти стандарты есть. А что? Откуда ты иначе узнаешь правду о языке, на котором пишешь?

Обычным юзерам хватит официальной документации по типу K&R.

При том, что примеры из K&R давно не компилируются.

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

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

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

Так во всех ЯП делают.

В Python пишут: «В Python 3.11 добавили что-то»

В Javascript пишут: «В новый стандарт языка Javascript добавили что-то»

Но да, сам стандарт я не думаю что многие JS программисты читали, но думаю многие знают что он существует.

fsb4000 ★★★★★
()

В некоторых проектах встречал такой макрос.

Проблему вижу одну: простого зануления не всегда достаточно, иногда это нужно делать атомарно перед освобождением памяти. А атомарная операция уже достаточно медленная, чтобы вносить её в стайлгайд.

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

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

Это не проблема вообще. Такой макрос покрывает 99% случаев и ни разу не вредит в оставшихся 1%.

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

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

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

В Паскале и потомках типа Ады так в общем и сделано. И ничо, никто не умер, производительность тоже не пострадала.

Да так и в C делают, когда об эффективности заботятся. ngx_str_t и аналоги во все поля.

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

Звучит как очередной способ унижения соискателей на собесах.

да вапще жесть ) и ЗП сразу напополам )

Если это действительно так, то я про это не слышал.

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

но по факту эти знания не носят прикладной характер, к счастью. пока ТС нас не унизит, запилив экзотическую архитектуру, полностью соответствующую стандарту )

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

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

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

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

https://blog.regehr.org/archives/761

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

Можно пример?

Любой. Там функции без объявления возвращаемого типа и старый стиль аргументов. Современные компиляторы такое не любят.

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

Хехехе.. писечка в том, что такой компилятор похоронит практически весь сишный код начиная прямо с glibc.

Вообще, ситуация довольно шизофреничная, да.

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

Чушь у тебя в штанах. А в C нет низкого уровня даже близко. То, что C довольно ограничен и убог по функциям, не делает его низкоуровневым ни разу.

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

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

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

Вы что-то слышали про совместимость на уровне ABI?

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

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

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

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

Отношение прямое. Низкий уровень – это когда высокоуровневый возни нету. Как, например, в Си. Освобождение переменной, например, не означает обнуление указателя. А выделение памяти – её обнуление. Ну и так далее.

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

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

Да никак. Программисту подкладываются очередные грабли, на этот раз безопасные. А потом в стандарте появится новый пункт про UB при использовании safe_free(). Далее найдется уязвимость с этим UB и hateyoufeel напишет, что программисты нифига не читают стандарт. Все просто.

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

Значение указателя после free не меняется и им можно пользоваться безо всяких UB. Например, вывести его через printf %p.

А потом ты напишешь что-то вроде

if(*p > 100) {
  do_something_good();
  free(p);
} else {
  do_something_bad();  
}
printf("%p\n", p);

и умный компилятор соптимизирует код до

do_something_bad();  
printf("%p\n", p);

ведь печать указателя даёт ему гарантию, что free не вызывался. UB нужен для оптимизации.

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

Низкий уровень – это когда высокоуровневый возни нету.

«Низкий уровень – это когда низкий уровень». Это не определение, чувак.

Освобождение переменной, например, не означает обнуление указателя. А выделение памяти – её обнуление. Ну и так далее.

В Джаве можно открыть файл, просрать объект и остаться с открытым файлом в процессе. Или попытаться прочитать из уже закрытого файла. Жаба – низкоуровневый язык?

Не упомянув при этом, как будут обнуляться все остальные указатели на этот регион. Как Вы это себе представляете?

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

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