Здравствуйте, adontz, Вы писали:
K>>Ну так было бы неплохо, например, иметь strlcpy()/strlcat() везде. "Везде" включает в себя стандарт. Так же было бы неплохо иметь там же [v]asprintf(). Ну так я же не называю системы, где нет перечисленного, кривыми в плане реализации libc? A>Если ты не заметил, то я отвечал на это A>
A>В высшей степени странное утверждение! Функция glibc fclose соответствует стандарту ANSI C, и в манах черным по белому написано, что ее поведение не определено в случае передачи ей инвалидного указателя (что, кстати, полностью соответствует стандарту).
A>Вообще непонятно, как ты хочешь обрабатывать передачу инвалидного УКАЗАТЕЛЯ функции, на нем что написано, что он кривой.
A>И просто показал, что функция никак не противореча стандарту может устойчиво распознавать невалидные указатели. Вот и всё.
Может. Но не должна.
A>А то что LIBC кривая, это ты меня с кем-то перепутал.
Это я в рамках общей дискуссии вообще и первого сообщения в частности.
Kemm wrote: > > Pzz>Строго говоря, в любой реализации этот список уже есть. Hint: exit() > Pzz>обязана закрыть все файлы, открытые через fopen(). И при этом не забыть > Pzz>сказать на них fflush(). > > Она обязана закрыть вообще все открытые файлы, не важно. Мне куда более > в этот момент интересна переносимая реализация потокобезопасного fopen() > со списком валидных файлов, не использующая блокировок. 8))
Хендлы/дескрипторы закрывает система. А вот FILE должна закрывать libc
(или, по крайней мере, проталкивать недописанное).
adontz wrote: > > Я как бы не очень понял, почему политика /библиотеки/ LIBC это свойство
Потому, что LIBC это как бы часть C
> /языка/ С и почему нельзя внести обсуждаемое изменение, если оно никак > не влияет на существующие программы и не мешает диагностировать ошибки > (они скрываются, просто больше не приводят к фатальным последствиям).
Проверять все в рантайме дорого. Проверять же только некоторые операции
бессмысленно. Если мы проверяем fclose(), то надо проверять и fwrite().
Скорость выполнения fwrite() от этого упадет.
> Я не прошу изменить стандарт, я спрашиваю чем это было бы плохо? Да
Это плохо для тех, кто рассчитывает на быстрые файловые операции.
Здравствуйте, adontz, Вы писали:
K>>И что? Будем два стандарта С держать? A>Я стандарт менять не собирался
Ну так тогда и надо писать в рамках стандарта. И расчитывать на какое-либо определенное поведение в случае, когда в стандарте английским по фоновому написано прямо противоположное — как минимум, странно.
K>>Хм... Великий труд — таскать с собой библиотечку из N функций... В любом случае, я вот как минимум всегда с собой таскаю реализацию strlcpy()/strlcat() из, afair, NetBSD. Просто потому, что это удобно. A>Как тут заметили список уже есть. Если писать обёртки, то мы зачем-то будет иметь два списка.
Есть. Только вот никто не гарантирует, в каком виде тот список, и так ли легко оттуда все это достать. Одна пробежка по нему в случае exit(3) или проверки при каждом flose(3) — несколько разные вещи.
K>>А вот возражения против обязательной проверки в рамках libc уже озвучили, и не одно. A>Это когда вы думали, что я из библиотечно функции буду в логи писать. Или я что-то упустил?
Размер/скорость. В принципе, не критично — кому нужна скорость или размер, те f*() использовать вряд ли будут. А вот возможное сокрытие ошибки уже плохо. Очень.
Здравствуйте, Pzz, Вы писали:
>> Pzz>Строго говоря, в любой реализации этот список уже есть. Hint: exit() >> Pzz>обязана закрыть все файлы, открытые через fopen(). И при этом не забыть >> Pzz>сказать на них fflush(). >> Она обязана закрыть вообще все открытые файлы, не важно. Мне куда более >> в этот момент интересна переносимая реализация потокобезопасного fopen() >> со списком валидных файлов, не использующая блокировок. 8)) Pzz>Хендлы/дескрипторы закрывает система. А вот FILE должна закрывать libc Pzz>(или, по крайней мере, проталкивать недописанное).
Ну, кто там что должен закрывать, afair, в стандарте не записано. Так что теоретически может FILE и ядро закрывать со сбросом буфера.
Kemm wrote: > > Pzz>Хендлы/дескрипторы закрывает система. А вот FILE должна закрывать libc > Pzz>(или, по крайней мере, проталкивать недописанное). > > Ну, *кто* там *что* должен закрывать, afair, в стандарте не записано. > Так что теоретически может FILE и ядро закрывать со сбросом буфера.
Может. Но я ни одного такого ядра не знаю
Я просто объясняю, что в любой практической реализации список открытых
файлов (в смысле, FILE) где-нибудь да лежит.
Здравствуйте, adontz, Вы писали:
A>А подумать, прежде чем писать можно было? Ей передаётся не абы какой указатель, а выделенный fopen. Что мешает хранить где-то внутри список всех указателей выделенных fopen и при вызове fread, fwrite, fclose проверять валидность переданного указателя простым его вхождением в список? Ничего не мешает, кроме лени и желания гнать понты.
Вот лень как раз и мешает писать программы правильно.
A>По сравнению со скоростью ввода-вывода это копейки.
Дескриптор не обязательно должен быть дескриптором файла на диске.
Обязательно бахнем! И не раз. Весь мир в труху! Но потом. (ДМБ)
K>>Hint: i86 не самое популярное семейство процессоров. A>Не самое популярное где?
Вообще, в абсолюте. По количеству процессоров в мире.
>Тогда уж назови самое популярное. Кстати позаботься, чтобы у самого популярного по твоей версии семейства не было аналога команды CMPXCHG
Посмотри на количество гаджетов вокруг тебя и посчитай количество процессоров. Мобильник — обычно два, DECT телефоны, факсы, наладонники (один, два), MP3 плееры; DVD; автомобили — черт знает сколько, я честно не знаю, но никак не меньше одного. Вобщем рынок PC/X86 очень маленький по сравнению с этим. В подавляющем большинстве перечисленных систем чаще всего используется ARM (и специализированные DSP). На ARM никакого CMPXCHG нету.
Здравствуйте, LelicDsp, Вы писали:
>>Тогда уж назови самое популярное. Кстати позаботься, чтобы у самого популярного по твоей версии семейства не было аналога команды CMPXCHG LD>Посмотри на количество гаджетов вокруг тебя и посчитай количество процессоров. Мобильник — обычно два, DECT телефоны, факсы, наладонники (один, два), MP3 плееры; DVD; автомобили — черт знает сколько, я честно не знаю, но никак не меньше одного. Вобщем рынок PC/X86 очень маленький по сравнению с этим. В подавляющем большинстве перечисленных систем чаще всего используется ARM (и специализированные DSP). На ARM никакого CMPXCHG нету.
А сколько калькуляторов.... Вобщем это конечно же профанация. В MP3 плеере и автомобиле никакого Линукса нет. Да и LIBC я там вряд ли увижу. Надо считать не процессоры вообще, а те для которых этот список реально нужен.
Кроме того, как тут кстати заметили, список уже есть и его не надо делать. А с блокировками он или без дело десятое.
Здравствуйте, adontz, Вы писали:
A>Повторюсь специально для тебя. fclose удаляет указатель из списка валидных. Зачем хранить 1000000 значений указателей для УЖЕ ЗАКРЫТЫХ файлов я не очень понимаю.
Чтобы не выдать этот указатель повторно.
И гарантировано отловить работу с невалидным указателем.
Пример:
f1 = fopen();
f2 = f1;
fclose(f1);
f1 = fopen(); // Допустим второй вызов fopen вернёт тот же указатель, что и первый вызов. Почему бы и нет?
fclose(f2); // Здесь не сломается,
fclose(f1); // а вот здесь сломается, хотя после всех "улучшательств" должно быть наоборот.
Здравствуйте, execve, Вы писали:
E>Чтобы не выдать этот указатель повторно. E>И гарантировано отловить работу с невалидным указателем. E>Пример: E>
E>f1 = fopen();
E>f2 = f1;
E>fclose(f1);
E>f1 = fopen(); // Допустим второй вызов fopen вернёт тот же указатель, что и первый вызов. Почему бы и нет?
E>fclose(f2); // Здесь не сломается,
E>fclose(f1); // а вот здесь сломается, хотя после всех "улучшательств" должно быть наоборот.
E>
// Начало работы. Список открытых файлов пуст.
f1 = fopen();
// f1 == 0x00100000, в списке (0x00100000)
f2 = f1;
// f1 == 0x00100000, f2 == 0x00100000, в списке (0x00100000)
fclose(f1);
// f1 == 0x00100000, f2 == 0x00100000, в списке ()
f1 = fopen(); // Допустим второй вызов fopen вернёт тот же указатель, что и первый вызов. Почему бы и нет?
// f1 == 0x00100000, f2 == 0x00100000, в списке (0x00100000)
fclose(f2); // Здесь не сломается,
// f1 == 0x00100000, f2 == 0x00100000, в списке ()
fclose(f1); // а вот здесь сломается, хотя после всех "улучшательств" должно быть наоборот.
// f1 == 0x00100000, f2 == 0x00100000, в списке (), указатель переданный в fclose отсутсвует в списке - ошибка распознана.
Здравствуйте, execve, Вы писали:
E>Сломается на закрытии f3. E>Хотя f3 тут совершенно не причём и должно сломаться на закрытии f2.
Во-первых, не сломается, а будет диагностированная ошибка. Сломалось бы без списка.
Во-вторых, ошибка всё таки будет диагностирована, а то что немного не там, ну так список слишком простая структура — из неё ИМХО больше не выжать.
Здравствуйте, adontz, Вы писали:
A>Во-первых, не сломается, а будет диагностированная ошибка. Сломалось бы без списка. A>Во-вторых, ошибка всё таки будет диагностирована, а то что немного не там, ну так список слишком простая структура — из неё ИМХО больше не выжать.
Как Вам уже сказали выше, используйте glibc-debug для отладки.
Обязательно бахнем! И не раз. Весь мир в труху! Но потом. (ДМБ)
Здравствуйте, ДимДимыч, Вы писали:
A>>Во-первых, не сломается, а будет диагностированная ошибка. Сломалось бы без списка. A>>Во-вторых, ошибка всё таки будет диагностирована, а то что немного не там, ну так список слишком простая структура — из неё ИМХО больше не выжать. ДД>Как Вам уже сказали выше, используйте glibc-debug для отладки.
Как я уже сказал, я не собираюсь переписывать libc или менять стандарт. Я просто показал, что fclose может определять валидность переданного ей указателя.
Здравствуйте, adontz, Вы писали:
A>>>Во-первых, не сломается, а будет диагностированная ошибка. Сломалось бы без списка. A>>>Во-вторых, ошибка всё таки будет диагностирована, а то что немного не там, ну так список слишком простая структура — из неё ИМХО больше не выжать. ДД>>Как Вам уже сказали выше, используйте glibc-debug для отладки.
A>Как я уже сказал, я не собираюсь переписывать libc или менять стандарт. Я просто показал, что fclose может определять валидность переданного ей указателя.
Может. Не спорю. Но нужно ли это? В некоторых случаях, таких как отладка — нужно. Для этого есть glibc-debug, например, которая проверяет валидность указателей, реализация собственных оберток и т.д. В остальных случаях — не нужно, потому как: 1) неразумно используется память и процессорное время; 2) это способствует распространению некачественного кода и таких же программистов.
Обязательно бахнем! И не раз. Весь мир в труху! Но потом. (ДМБ)
Здравствуйте, ДимДимыч, Вы писали:
ДД>Может. Не спорю. Но нужно ли это? В некоторых случаях, таких как отладка — нужно. Для этого есть glibc-debug, например, которая проверяет валидность указателей, реализация собственных оберток и т.д. В остальных случаях — не нужно, потому как: 1) неразумно используется память и процессорное время; 2) это способствует распространению некачественного кода и таких же программистов.
Память не будет неразумно использоватся, потому что список и так уже есть. Процессорное время да — но поиск в списке из нескольких десятков элементов мелочи по сравнению со скоростью ввода-вывода.
Дело в том что в релизе тоже есть ошибки, но там glibc-debug не используют. И ИМХО лучше если библиотека вернёт тебе некоторый код ошибки, который будет обработан, чем если приложение просто рухнет. Лучше не для тебя (dump был бы весьма полезен), а для конечного пользователя.
Заметь в первом сообщении речь шла о программе, которую портировали. То есть когда-то её написали и она работала себе и работала с этой ошибкой, но потом её решили портировать и версия LIBC на новой платформе уже от старой ошибки рушит программу.
Так что рассуждать о том, что мол "не надо два раза закрывать файл" это конечно хорошо, но к реальности не имеет отношения. Бывает, что и закрывают. И я бы предпочёл, что бы такие вещи из разряда error перешли в warning.
На самом деле мои слова тоже на ветер. LIBC никто не препишет, стандарт не изменят, а файлы будут по прежнему закрывать по два раза.
Здравствуйте, adontz, Вы писали:
ДД>>Может. Не спорю. Но нужно ли это? В некоторых случаях, таких как отладка — нужно. Для этого есть glibc-debug, например, которая проверяет валидность указателей, реализация собственных оберток и т.д. В остальных случаях — не нужно, потому как: 1) неразумно используется память и процессорное время; 2) это способствует распространению некачественного кода и таких же программистов.
A>Память не будет неразумно использоватся, потому что список и так уже есть.
Неужели? Где он и зачем?
A>Процессорное время да — но поиск в списке из нескольких десятков элементов
Список держать необязательно, достаточно массив из OPEN_MAX элементов.
A>мелочи по сравнению со скоростью ввода-вывода.
Я уже говорил, дескриптор не обязательно будет дескриптором открытого файла на диске. Это может быть файл устройства, именованый канал, etc.
A>Дело в том что в релизе тоже есть ошибки, но там glibc-debug не используют. И ИМХО лучше если библиотека вернёт тебе некоторый код ошибки, который будет обработан, чем если приложение просто рухнет. Лучше не для тебя (dump был бы весьма полезен), а для конечного пользователя.
Для конечного пользователя лучше всего было бы иметь качественный, т.е. правильно написаный и отлаженый продукт.
A>Заметь в первом сообщении речь шла о программе, которую портировали. То есть когда-то её написали и она работала себе и работала с этой ошибкой, но потом её решили портировать и версия LIBC на новой платформе уже от старой ошибки рушит программу.
Если бы программа была написана идеологически правильно, этой ошибки не возникло бы.
A>Так что рассуждать о том, что мол "не надо два раза закрывать файл" это конечно хорошо, но к реальности не имеет отношения. Бывает, что и закрывают.
Бывает. Машины ненадежны, но люди еще ненадежнее. Но это не повод обвинять в кривости библиотеку, которая работает в соответствии со стандартом.
А>И я бы предпочёл, что бы такие вещи из разряда error перешли в warning.
Тогда может ты предложишь проверять на валидность указатели в realloc, free, pthread_create, sem_post и т.д. ?
Для быстрой и дешевой разработки ПО, некритичного к кривости рук программиста, существуют соответствующие технологии и языки.
Обязательно бахнем! И не раз. Весь мир в труху! Но потом. (ДМБ)
A>>мелочи по сравнению со скоростью ввода-вывода. ДД>Я уже говорил, дескриптор не обязательно будет дескриптором открытого файла на диске. Это может быть файл устройства, именованый канал, etc.
Всё равно, поиск в списке из нескольких десятков элементов это мелочи. Ввод-вывод крайне редко является узким местом. А если является, то меняют аппаратуру, а не переписывают программу.
ДД>Для конечного пользователя лучше всего было бы иметь качественный, т.е. правильно написаный и отлаженый продукт. ДД>Если бы программа была написана идеологически правильно, этой ошибки не возникло бы.
Вот давай только без демагогии, ладно? Пользователь никогда не получает полностью отлаженный продукт. А тыкать в людей правильной идеологией некультурно. Как будто кто-то специально делает ошибки.
ДД>Бывает. Машины ненадежны, но люди еще ненадежнее. Но это не повод обвинять в кривости библиотеку, которая работает в соответствии со стандартом.
А где я обвиял в кривости? Ты ни с кем меня не перепутал?
ДД>Тогда может ты предложишь проверять на валидность указатели в realloc, free, pthread_create, sem_post и т.д.?
А почему нет? Идеология не позволяет?
ДД>Для быстрой и дешевой разработки ПО, некритичного к кривости рук программиста, существуют соответствующие технологии и языки.
Кривизна рук тут ни при чём. Ошибки делают все. Я не очень понимаю, зачем надо гордится тем, что "язык на котором я программирую позволяет совершать более изощерённые ошибки" и тем более лелеять это как святыню.