adontz wrote: > > А подумать, прежде чем писать можно было? Ей передаётся не абы какой > указатель, а выделенный fopen. Что мешает хранить где-то внутри список > всех указателей выделенных fopen и при вызове fread, fwrite, fclose > проверять валидность переданного указателя простым его вхождением в > список? Ничего не мешает, кроме лени и желания гнать понты. По сравнению > со скоростью ввода-вывода это копейки. Те же дескрипторы в Windows это > сплошь указатели или индексы в таблицах, однако использование левого > дескриптора не приводит ни к какому краху. UB на сегодня это плохой тон > или детский сад, уж сам выбери.
1) В Виндовсе тоже есть fopen(). С теми же самыми проблемами, как и в Линухе
2) Виндовсный handle'овый интерфейс к файлам надо сравнивать с
юниксовским интерфейсом, работающим через дескрипторы, а не с stdio
3) Стиль языка C заключается, в частности, в том, что библиотека и
компилятор доверяют программисту. Сказали fclose() два раза, значит
будем закрывать файл два раза. Сказали поделить на ноль, значит будем
делить на ноль. Для тех, кто не согласен с такой политикой, существуют
"безопасные" языки программирования. Там все, что надо, проверяется.
Платой за удобства обычно является потеря эффективности.
Кирпа В.А. wrote:
> Здравствуйте, ДимДимыч, Вы писали: > > > ДД>Не забывайте, что FILE — это структура, и fopen() распределяет память > под нее, а fclose() освобождает. При повторном вызове fclose аргумент уже > указывает неизвестно на что и close(2) не может даже прочитать значение > дескриптора. close(2), кстати, корректно возвращает "Bad file descriptor". > ДД>Или вы предлагаете при каждом free() делать проверку на валидность > блока? > > Ну вот и начался конструктивный диалог > Я веду к тому что в библиотеке ввода/вывода необходим список открытых > файлов что-то типа std::vector<FILE *> > в который fopen добавляет а fclose удаляет > Тогда проверка на валидность указателя FILE * элементарна > > Вывод: реализация библиотеки ввода/вывода в Linux — кривовата.
В высшей степени странное утверждение! Функция glibc fclose соответствует
стандарту ANSI C, и в манах черным по белому написано, что ее поведение не
определено в случае передачи ей инвалидного указателя (что, кстати,
полностью соответствует стандарту).
Вообще непонятно, как ты хочешь обрабатывать передачу инвалидного УКАЗАТЕЛЯ
функции, на нем что написано, что он кривой.
Рекомендую читать маны, особенно по системным вызовам open, close, и
не ...здеть о том, что "реализация библиотеки ввода/вывода в Linux —
кривовата".
Здравствуйте, Кирпа В.А., Вы писали:
_>>немного непонятная притензий для меня, это "кривоватая" реализация _>>помогла вам найти и исправить ошибку КВА>Так ошибки не было Ну подумаеш два раза закрыли файл
Ошибка была.
КВА>Для надежности
За такую "надежность" гнать надо тряпками, пропитанными известной жидкостью. Давайте еще для надежности два-три раза insert в sql делать — мало ли...
Кирпа В.А. wrote: > > Ну вот и начался конструктивный диалог > Я веду к тому что в библиотеке ввода/вывода необходим список открытых > файлов > что-то типа std::vector<FILE *> > в который fopen добавляет а fclose удаляет > Тогда проверка на валидность указателя FILE * элементарна
Проблема с файлами — частный случай проблемы с аллокацией памяти в C.
Постоянные проверки снизили бы эффективность. А зачем тогда вообще нужна
ручная аллокация, если плевать на эффектовность?
Кстати, отладочные версии библиотек для работы с памятью существуют. Они
проверяют все, что надо.
> Вывод: реализация библиотеки ввода/вывода в Linux — кривовата
А при чем здесь Linux? Это не Linux, а ANSI C. С тем, что C это не язык
для идиотов, спорить не буду. Для идиотов существует Visual Basic
Kemm wrote: > > LD>>Но его придется делать потокобезопасным, > A>Это хорошо проработанная задача. Делается даже без блокировок. > > Ну-ка, ну-ка... Потокобезопасную реализацию fopen() со списком валидных > 'FILE *' в студию.
Строго говоря, в любой реализации этот список уже есть. Hint: exit()
обязана закрыть все файлы, открытые через fopen(). И при этом не забыть
сказать на них fflush().
Но тем не менее, это не значит, что fclose() _обязан_ проверять файл на
валидность.
Здравствуйте, cattus, Вы писали:
C>В высшей степени странное утверждение! Функция glibc fclose соответствует C>стандарту ANSI C, и в манах черным по белому написано, что ее поведение не C>определено в случае передачи ей инвалидного указателя (что, кстати, C>полностью соответствует стандарту).
В данном случае соответсвие стандарту вряд ли можно назвать плюсом.
C>Вообще непонятно, как ты хочешь обрабатывать передачу инвалидного УКАЗАТЕЛЯ функции, на нем что написано, что он кривой.
А подумать, прежде чем писать можно было? Ей передаётся не абы какой указатель, а выделенный fopen. Что мешает хранить где-то внутри список всех указателей выделенных fopen и при вызове fread, fwrite, fclose проверять валидность переданного указателя простым его вхождением в список? Ничего не мешает, кроме лени и желания гнать понты. По сравнению со скоростью ввода-вывода это копейки. Те же дескрипторы в Windows это сплошь указатели или индексы в таблицах, однако использование левого дескриптора не приводит ни к какому краху. UB на сегодня это плохой тон или детский сад, уж сам выбери.
C>Рекомендую читать маны, особенно по системным вызовам open, close, и не ...здеть о том, что "реализация библиотеки ввода/вывода в Linux — кривовата".
Рекомендую думать, что говоришь и как говоришь. О того что кто-то в твойм понимании пи@@ит твои слова не стали весомее, а мысли умнее.
Здравствуйте, Tanker, Вы писали:
T>Здравствуйте, srggal, Вы писали:
S>>After the call to fclose(), any use of stream results in undefined behavior.
T>Вот такого как раз быть и не должно. Функция должна вернуть код ошибки.
ГМ, если Вы не поняли, то это цитирование POSIX SUSV3.
ИМХО не очень правильно переть против танка с шашкой, и кричать, что он должен свернуть
On Mon, 12 Dec 2005 11:37:36 -0000, Кирпа В.А. <5450@users.rsdn.ru> wrote:
[]
> Покатим бочку на Linux дальше > Это же как надо тупо реализовать библиотечные функции ввода/вывода > чтобы повторное закрытие файла ломало heap > кстати повторное закрытие файла в SUN, Windows ничего вредного не делает
Сиди в виндозе и радуйся жизни.
> КВА>>А возмутило меня другое Анализ лога valgrind показал что библиотечные > КВА>>функции fprintf, fclose вовсю юзают malloc, free > > E>А какие функции они должны юзать? > > Раз они юзают malloc, free то пусть будут добры не попадать в условия когда > портится heap (например повторное закрытие файла)
Лучше пусть они маскируют ошибки в твоем коде, так?
Здравствуйте, MaximE, Вы писали:
ME>Сиди в виндозе и радуйся жизни.
Грубить-то зачем? После подобных ответов окружающие начинают к юниксоидам относиться как красноглазым пионерам.
ME>Лучше пусть они маскируют ошибки в твоем коде, так?
Тем более, что выдвинутый тобою тезис, сводящийся к тому, что в операционной системе всякого рода защита от кривых приложений — вещь ненужная, не выдерживает никакой критики.
Я вот чего не пойму, доколе будет холиварз в этой ветке ?
Эту ветку давно пора перенемти в Философию, Ибо конструктивные ответы были даны, но все выродилось в банальный холиварз.
ОТчего в форуме по С/С++ не приходит в голову кричать во весь голос — а мне не нравится как написан стандарт ?
А если и находятся индивидумы — то никто с нимим не флеймит ?
МОДЕРАТОРЫ ИМХО — ПОРА ПЕРЕНОСИТЬ
Нет желания копаться во всем, приведу только ссылку на свой пост: здесь
Здравствуйте, adontz, Вы писали:
A>>>мелочи по сравнению со скоростью ввода-вывода. ДД>>Я уже говорил, дескриптор не обязательно будет дескриптором открытого файла на диске. Это может быть файл устройства, именованый канал, etc.
A>Всё равно, поиск в списке из нескольких десятков элементов это мелочи. Ввод-вывод крайне редко является узким местом. А если является, то меняют аппаратуру, а не переписывают программу.
Бывают открыты и десятки тысяч файлов, например на файл-сервере.
Вы такое впечатление, рассматриваете эту проблему в применении для разных относительно
простых десктопно-офисных программ и не заметили, что ваш подход создаёт на самом деле
серьёзную проблему.
Допустим мы будем всегда проверять на повторное закрытие, тогда мы должны хранить не
только список открытых файлов, но и список всех закрытых. Если списка закрытых файлов не будет, выйдет риск при повторном закрытии закрыть файл, со вновь полученным
дескриптором, то есть, мы не избавимся от неопределённого поведения, а только растратим лишние ресурсы на список и его проверку.
Кроме того, отловить такую ошибку может быть сильно тяжелее. Представьте себе многопоточную программу, в одном потоке закрыли два раза файл, а в другом на ровном
месте возникла ошибка на файловых операциях. Я вас уверяю, сообразить в этом случае
из-за чего возникла ошибка окажется тяжело, тем более данная ошибка будет плохо воспроизводимой, при маленькой вероятности повторной выдаче одинакового номера дескриптора. Самый подлый для отладки вид ошибок, проявляющихся нерегулярно, очень редко, да ещё и в совершенно других файлах относительно места возникновения.
И зачем козе баян, если от ошибок он не избавляет, загоняя их вглубь, делая опасными для работы, а ресурсы лишние тратятся?
А если вы полагаете нужным хранить весь список, в том числе и открытых файлов, то я только руками разведу: утечка памяти и расход ресурсов на ерунду никак хорошим программированием нельзя назвать.
При том замечу, в каких-то частных случаях можно и списки лишние хранить и проверки делать и прочее, для чего делаются обёртки и свой код под эти случаи. Вы же говорили об универсальном подходе.
Мой вывод: всегда проверять на уровне системных библиотек правильность fclose, free и др. на случай неверного указателя, кроме спецзначений (NULL и др.) или их диапазона (области пользовательских/системных данных) в корне неверно и способствует возникновению труднообнаруживаемых ошибок.
Здравствуйте, Кирпа В.А., Вы писали:
КВА>Я лишь знаю что системная библиотека ввода/вывода не должна разрушать кучу ни при каких условиях КВА>Повторное fclose() должно завершиться с ошибкой В errno должен быть установлен соотвествующий код ошибки
fclose принимает на вход указатель.
Вполне возможно, что он что-то пишет по этому указателю.
Если ты подсовываешь ему указатель неизвестно на что, то как он обнаружит, что этот указатель невалидный?
В результате и получаем странное: разрушение кучи.
На самом деле проверку на валидность указателя можно сделать (free с какими-то флагами ЕМНИПС уже умеет это), но её добавление ударит либо по производительности, либо по объёму используемой памяти.
Здравствуйте, ДимДимыч, Вы писали:
ДД>Здравствуйте, Кирпа В.А., Вы писали:
КВА>>Раз они юзают malloc, free то пусть будут добры не попадать в условия когда КВА>>портится heap (например повторное закрытие файла)
ДД>Хм... не нужно попадать в условия, когда возможно повторное закрытие файла.
Так и знал что всех собак повесят на меня
Я не любитель повторного закрытия файла и знаю что закрыть файл необходимо и достаточно один раз
Как я говорил я просто портировал чужой проект
Я лишь знаю что системная библиотека ввода/вывода не должна разрушать кучу ни при каких условиях
Повторное fclose() должно завершиться с ошибкой В errno должен быть установлен соотвествующий код ошибки
А возражения MaximE Ну и сиди в Винде и радуйся жизни не принимаются
Здравствуйте, Кирпа В.А., Вы писали:
КВА>Покатим бочку на Linux дальше КВА>Это же как надо тупо реализовать библиотечные функции ввода/вывода КВА>чтобы повторное закрытие файла ломало heap КВА>кстати повторное закрытие файла в SUN, Windows ничего вредного не делает
Линух то тут причеи, там с файлами работают через open, close, read, write.
Реализация fopen, fclose зависит от того какой ты компилятор используешь,
вернеет от поставляемой вместе с ним реализация стандартной библиотеки. Если тебя
что то не устраивает, пиши авторам этой самой библиотеки.
Здравствуйте, adontz, Вы писали:
A>Кроеме того я не сказал, что дампы плохо. Я сказал что плохо — падающее приложение и лучше до этого не доводить.
ГМ,если бы Вы действительно так считали, то пришли бы к томуже выводу, что и я
Приложение, которое не падает должно следовать стандартам которым соответсвует ОС, под которую написано приложение. В противном случае UB.
Неправильность Вашей позиции ( я считаю таковой ожидание умной диагностики от рантайм, но если ошибся — поправьте ) и привела АТ к созданию этого топика. Он не стал изучать POSIX, а доверился смартовому рантайму от
SUN.
Портировал я давеча один непутевый код с SUN на Linux
О результате такого подхода мы можем судить из его сообщения, и флейма, который оно вызвало.
ИМХО: стандарты как минимум в ИТ, пишутся таким образом, дабы несвязывать разработчикам стандартизованного ПО руки, и даже наоборот, предоставить свободу реализации. Можно приводить много примеров требований из разных стандартов, которые на первый взгляд необязательны и совсем неочевидны. НО, повторюсь: ЧТОБЫ ПРОГРАММА НЕ ПАДАЛА, ОНА ДОЛЖНА СООТВЕТСВОВАТЬ СТАНДАРТАМ ( каким — уточнять не буду, но как минимум языка и ОС под которую написана ).
Портировал я давеча один непутевый код с SUN на Linux
И программа все время валилась c Segmentation fault
притом самое интересное что было это внутри fclose()
Спасибо людям что открыли мне прекрассный тулз valgrind
Он и раскрыл мне глаза на то что в одном месте файл открытый на чтение
закрывался дважды (заметьте не тот файл при закрытии которого был
Segmentation fault)
А возмутило меня другое Анализ лога valgrind показал что библиотечные
функции fprintf, fclose вовсю юзают malloc, free
Не порядок однако
Ошибки при работе с памятью в моих программах не должны влиять на работу
библиотечных функций и наоборот
Повторное (случайное) закрытие файла влечет за собой харакири всей кучи
Здравствуйте, Кирпа В.А., Вы писали:
КВА>Раз они юзают malloc, free то пусть будут добры не попадать в условия когда КВА>портится heap (например повторное закрытие файла)
Хм... не нужно попадать в условия, когда возможно повторное закрытие файла.
Обязательно бахнем! И не раз. Весь мир в труху! Но потом. (ДМБ)
On Mon, 12 Dec 2005 13:02:07 -0000, voxel3d <20383@users.rsdn.ru> wrote:
> ME>Сиди в виндозе и радуйся жизни. > > Грубить-то зачем? После подобных ответов окружающие начинают к юниксоидам относиться как красноглазым пионерам.
Грубости не было.
> ME>Лучше пусть они маскируют ошибки в твоем коде, так? > > Тем более, что выдвинутый тобою тезис, сводящийся к тому, что в операционной системе всякого рода защита от кривых приложений — вещь ненужная, не выдерживает никакой критики.
Что за критика такая?
В Linux ты не обрушишь kernel, он защищен от кривых рук, свое же приложение — пожалуйста.
On Mon, 12 Dec 2005 13:34:42 -0000, Кирпа В.А. <5450@users.rsdn.ru> wrote:
[]
> Я веду к тому что в библиотеке ввода/вывода необходим список открытых файлов > что-то типа std::vector<FILE *> > в который fopen добавляет а fclose удаляет > Тогда проверка на валидность указателя FILE * элементарна
Мне он не нужен, я не хочу платить за это. Если тебе это нужно — заведи для своего приложения.
Здравствуйте, Кирпа В.А., Вы писали:
КВА>>>Для надежности K>>За такую "надежность" гнать надо тряпками, пропитанными известной жидкостью. Давайте еще для надежности два-три раза insert в sql делать — мало ли... КВА>Ты наверное юмора не понимаеш? "Для надежности" это надо читать в кавычках
Я так и прочитал, если обратить внимание на выделенное.
Считать, что система должна (кому?!) отслеживать криворуких программистов — путь в никуда. Именно это Вы и декларировали в первых постах.
Следующее утверждение, например, почему при использовании gethostbyname() возникает такая "фигня" в multithread софте. Нафиг-нафиг-нафиг такие претензии. Никто не общал, что fclose() будет себя корректно вести в подобной ситуации. Ни стандарт Сей, ни POSIX, ни SUSv3.
Здравствуйте, srggal, Вы писали:
ME>>Мы говорим про приложение, не про модуль ядра.
S>Дык просото к слову пришлось
S>ИМХО фраза пафосная про "не обрушишь kernel" вот и не сдержался, благо — дурацкое дело не хитрое, и сам, допустил подобный баг по неграмотности
Слава богу, модуль ядра нельзя загрузить из-под не-рута. А рутом систему можно изрушить и менее изощренными способами.
It's kind of fun to do the impossible (Walt Disney)
Здравствуйте, adontz, Вы писали:
A>В данном случае соответсвие стандарту вряд ли можно назвать плюсом.
Когда и unix-like ОС начнут действовать по принципу M$^H^H "если наши функции не соответствуют стандарту — тем хуже для стандарта", то я уже даже и не знаю, куды бечь надо будет. В другую вселенную, не иначе.
C>>Вообще непонятно, как ты хочешь обрабатывать передачу инвалидного УКАЗАТЕЛЯ функции, на нем что написано, что он кривой. A>А подумать, прежде чем писать можно было? Ей передаётся не абы какой указатель, а выделенный fopen. Что мешает хранить где-то внутри список всех указателей выделенных fopen и при вызове fread, fwrite, fclose проверять валидность переданного указателя простым его вхождением в список? Ничего не мешает, кроме лени и желания гнать понты. По сравнению со скоростью ввода-вывода это копейки. Те же дескрипторы в Windows это сплошь указатели или индексы в таблицах, однако использование левого дескриптора не приводит ни к какому краху. UB на сегодня это плохой тон или детский сад, уж сам выбери.
Детский сад — это писать код, не соответствующий стандарту. Мне куда дороже более быстрое выполнение (даже если это 1 процент, хотя может быть значительно больше в Вашем случае), чем детские ошибки. gcov + valgrind творят чудеса, к сведению.
C>>Рекомендую читать маны, особенно по системным вызовам open, close, и не ...здеть о том, что "реализация библиотеки ввода/вывода в Linux — кривовата". A>Рекомендую думать, что говоришь и как говоришь. О того что кто-то в твойм понимании пи@@ит твои слова не стали весомее, а мысли умнее.
Тише, горячие парни. Модератора на вас обоих нет... 8))
Здравствуйте, adontz, Вы писали:
LD>>Дело не в сложно/несложно. Не сложнее чем компилятор. Непонятно зачем это нужно. A>Чтобы приложение не падало. Пусть себе пишет в log файл что была попытка закрыть несуществуещий дескриптор. Скажешь не лучше?
Напиши обертку вокруг fopen()/fclose(), которая этим будет заниматься. Медленнее не будет, зато будет правильно. А то в лог писать... В какой лог, простите?..
Здравствуйте, adontz, Вы писали:
K>>Напиши обертку вокруг fopen()/fclose(), которая этим будет заниматься. Медленнее не будет, зато будет правильно. А то в лог писать... В какой лог, простите?.. A>Да хоть в файл. Хотя БД конечно лучше, но просто не всегда есть.
В файл? Ой, а у меня тут все read-only, и логи я в syslog пишу, какая незадача. Или еще куда. В последовательный порт. Чем обертка-то не устраивает.
adontz wrote: > C>Во время отладки такая ошибка элементарно обнаруживается по > backtrace'у из fclose. > Блин, ну читайте всю ветку, я же уже раза 3 это объяснял. > *А что если ошибка проявляется только на клиентской машине?* Что, не > бывает так?
Пусть шлют coredump, по которому можно посмотреть stacktrace.
adontz wrote: > Это замечательно конечно, примечик такой штуки даже на CodeProject есть, > но по сути неприятная выходит ситуация. Была ошибка после которой можно > было восстановится, а вместо этого программа валится, теряются данные и > т.д. и т.п.
Не "можно было восстановиться", а "можно было сделать вид, что ничего не
произошло". Причем с возможными катастрофическими последствиями.
Уж лучше пусть программа сразу упадет, чем будет делать вид.
Здравствуйте, Stoune, Вы писали:
S>Как как раз тот разработчик встроенных систем, отправлю обоих пить пиво в сторонке и нас не трогать, потому как Линуха у меня не будет и Винды тем более, потому что не поместится да и не нужен мне он. и вообще у самого крутого проца из серии 32К флеш памяти, и около 16К Рам, ну с господа куда вы собираетесь свои дескрипторы засовывать .
Здравствуйте, Кирпа В.А., Вы писали:
КВА>Портировал я давеча один непутевый код с SUN на Linux
КВА>И программа все время валилась c Segmentation fault КВА>притом самое интересное что было это внутри fclose() КВА>Спасибо людям что открыли мне прекрассный тулз valgrind КВА>Он и раскрыл мне глаза на то что в одном месте файл открытый на чтение КВА>закрывался дважды (заметьте не тот файл при закрытии которого был КВА>Segmentation fault)
close(fd);
fd = -1;
ну и анализировать возврат из close.
КВА>А возмутило меня другое Анализ лога valgrind показал что библиотечные КВА>функции fprintf, fclose вовсю юзают malloc, free
Здравствуйте, execve, Вы писали:
E>Здравствуйте, Кирпа В.А., Вы писали:
КВА>>Портировал я давеча один непутевый код с SUN на Linux
КВА>>И программа все время валилась c Segmentation fault КВА>>притом самое интересное что было это внутри fclose() КВА>>Спасибо людям что открыли мне прекрассный тулз valgrind КВА>>Он и раскрыл мне глаза на то что в одном месте файл открытый на чтение КВА>>закрывался дважды (заметьте не тот файл при закрытии которого был КВА>>Segmentation fault)
E>
E>close(fd);
E>fd = -1;
E>
E>ну и анализировать возврат из close.
Покатим бочку на Linux дальше
Это же как надо тупо реализовать библиотечные функции ввода/вывода
чтобы повторное закрытие файла ломало heap
кстати повторное закрытие файла в SUN, Windows ничего вредного не делает
КВА>>А возмутило меня другое Анализ лога valgrind показал что библиотечные КВА>>функции fprintf, fclose вовсю юзают malloc, free
E>А какие функции они должны юзать?
Раз они юзают malloc, free то пусть будут добры не попадать в условия когда
портится heap (например повторное закрытие файла)
КВА>Покатим бочку на Linux дальше КВА>Это же как надо тупо реализовать библиотечные функции ввода/вывода КВА>чтобы повторное закрытие файла ломало heap КВА>кстати повторное закрытие файла в SUN, Windows ничего вредного не делает
В Windows они ничего вредного не делают, потому что как я предполагаю, все эти функции реализованы через CreateFile(), CloseHandle(). А когда им передать неправильный хэндл, они его просто не находят в таблице открытых хэндлов и всё. В Линуксе наверно никаких таблиц нет, функция просто работает с указателем, считая
его правильным по умолчанию.
Здравствуйте, Кирпа В.А., Вы писали:
КВА>Как я говорил я просто портировал чужой проект
if (f)
{
fclose(f);
f = NULL;
}
КВА>Я лишь знаю что системная библиотека ввода/вывода не должна разрушать кучу ни при каких условиях КВА>Повторное fclose() должно завершиться с ошибкой В errno должен быть установлен соотвествующий код ошибки
Не забывайте, что FILE — это структура, и fopen() распределяет память под нее, а fclose() освобождает. При повторном вызове fclose аргумент уже указывает неизвестно на что и close(2) не может даже прочитать значение дескриптора. close(2), кстати, корректно возвращает "Bad file descriptor".
Или вы предлагаете при каждом free() делать проверку на валидность блока?
Обязательно бахнем! И не раз. Весь мир в труху! Но потом. (ДМБ)
ДД>Не забывайте, что FILE — это структура, и fopen() распределяет память под нее, а fclose() освобождает. При повторном вызове fclose аргумент уже указывает неизвестно на что и close(2) не может даже прочитать значение дескриптора. close(2), кстати, корректно возвращает "Bad file descriptor". ДД>Или вы предлагаете при каждом free() делать проверку на валидность блока?
Ну вот и начался конструктивный диалог
Я веду к тому что в библиотеке ввода/вывода необходим список открытых файлов
что-то типа std::vector<FILE *>
в который fopen добавляет а fclose удаляет
Тогда проверка на валидность указателя FILE * элементарна
Вывод: реализация библиотеки ввода/вывода в Linux — кривовата
Здравствуйте, Кирпа В.А., Вы писали:
ДД>>Не забывайте, что FILE — это структура, и fopen() распределяет память под нее, а fclose() освобождает. При повторном вызове fclose аргумент уже указывает неизвестно на что и close(2) не может даже прочитать значение дескриптора. close(2), кстати, корректно возвращает "Bad file descriptor". ДД>>Или вы предлагаете при каждом free() делать проверку на валидность блока? КВА>Ну вот и начался конструктивный диалог КВА>Я веду к тому что в библиотеке ввода/вывода необходим список открытых файлов КВА>что-то типа std::vector<FILE *> КВА>в который fopen добавляет а fclose удаляет КВА>Тогда проверка на валидность указателя FILE * элементарна
КВА>Вывод: реализация библиотеки ввода/вывода в Linux — кривовата
Странный вывод... Почему тогда нет претензий к коредампу на, к примеру, вот это:
int *a = 0xdeadbeaf;
*a = 17;
? И к прочим радостям при работе с невалидной памятью?..
Здравствуйте, Кирпа В.А., Вы писали:
КВА>Ну вот и начался конструктивный диалог КВА>Я веду к тому что в библиотеке ввода/вывода необходим список открытых файлов КВА>что-то типа std::vector<FILE *> КВА>в который fopen добавляет а fclose удаляет
Допустим, программа открывает файл f1, получает как результат указатель p1. fopen() добавляет этот указатель в список валидных. Программа работает с ним, потом закрывает. fclose() закрывает f1 и удаляет p1 из списка. Программа открывает другой файл f2, указатель возвращается численно равный p1 (ну, аллокатор так вернул). Потом следует повторное закрытие f1 и работа с f2. Каковы будут последствия?
КВА>Вывод: реализация библиотеки ввода/вывода в Linux — кривовата
В данном случае реализация библиотеки критична к грубым ошибкам в приложении.
Обязательно бахнем! И не раз. Весь мир в труху! Но потом. (ДМБ)
Здравствуйте, ДимДимыч, Вы писали:
ДД>Здравствуйте, Кирпа В.А., Вы писали:
КВА>>Ну вот и начался конструктивный диалог КВА>>Я веду к тому что в библиотеке ввода/вывода необходим список открытых файлов КВА>>что-то типа std::vector<FILE *> КВА>>в который fopen добавляет а fclose удаляет
ДД>Допустим, программа открывает файл f1, получает как результат указатель p1. fopen() добавляет этот указатель в список валидных. Программа работает с ним, потом закрывает. fclose() закрывает f1 и удаляет p1 из списка. Программа открывает другой файл f2, указатель возвращается численно равный p1 (ну, аллокатор так вернул). Потом следует повторное закрытие f1 и работа с f2. Каковы будут последствия?
Никаких
Работа с f2 уже невозможна потому что он закрыт Любая работа с файлом не только fclose (но и fprintf и т д) идут через валидацию указателя на файл
FILE *f1 = fopen("/tmp/1", "w");
FILE *f2 = f1;
fclose(f2);
fprintf(f1, "%s\n", "Ups"); // упс файл закрыт
fclose(f1); // упс файл закрыт
КВА>>Вывод: реализация библиотеки ввода/вывода в Linux — кривовата
ДД>В данном случае реализация библиотеки критична к грубым ошибкам в приложении.
Здравствуйте, ДимДимыч, Вы писали:
КВА>>>Вывод: реализация библиотеки ввода/вывода в Linux — кривовата
ДД>>В данном случае реализация библиотеки критична к грубым ошибкам в приложении.
ДД>Кстати, при повторном вызове fclose() сразу же после первого вызова glibc вполне внятно сообщает о ДД>
Здравствуйте, Кирпа В.А., Вы писали:
КВА>Здравствуйте, ДимДимыч, Вы писали:
КВА>>>>Вывод: реализация библиотеки ввода/вывода в Linux — кривовата
ДД>>>В данном случае реализация библиотеки критична к грубым ошибкам в приложении.
Ваше приложение криво написанно — 2 раза закрывается 1 файл.
Действия системы при детектировании этого события — закрыть ваше приложение.
Не вижу никаких проблемм. . Правда закрывают вас не совсем коректно это да.
Здравствуйте, Кирпа В.А., Вы писали:
КВА>Здравствуйте, ДимДимыч, Вы писали:
КВА>>>>Вывод: реализация библиотеки ввода/вывода в Linux — кривовата
ДД>>>В данном случае реализация библиотеки критична к грубым ошибкам в приложении.
ДД>>Кстати, при повторном вызове fclose() сразу же после первого вызова glibc вполне внятно сообщает о ДД>>
_>а к реализации free и malloc у вас нет притензий?
_>тоже библиотечные функции и тоже могут разрушить кучу.
_>немного непонятная притензий для меня, это "кривоватая" реализация _>помогла вам найти и исправить ошибку
Так ошибки не было Ну подумаеш два раза закрыли файл
Для надежности
Так нет эту оплошность разработчики библиотеки ввода-вывода умудрились
преобразовать в Segmentation fault
Здравствуйте, Кирпа В.А., Вы писали:
ДД>>Допустим, программа открывает файл f1, получает как результат указатель p1. fopen() добавляет этот указатель в список валидных. Программа работает с ним, потом закрывает. fclose() закрывает f1 и удаляет p1 из списка. Программа открывает другой файл f2, указатель возвращается численно равный p1 (ну, аллокатор так вернул). Потом следует повторное закрытие f1 и работа с f2. Каковы будут последствия?
КВА>Никаких КВА>Работа с f2 уже невозможна потому что он закрыт Любая работа с файлом не только fclose (но и fprintf и т д) идут через валидацию указателя на файл
В итоге Вам все равно приходится искать, где был лишний вызов fclose() и принимать соответствующие меры.
Обязательно бахнем! И не раз. Весь мир в труху! Но потом. (ДМБ)
Здравствуйте, Kemm, Вы писали:
K>Здравствуйте, Кирпа В.А., Вы писали:
_>>>немного непонятная притензий для меня, это "кривоватая" реализация _>>>помогла вам найти и исправить ошибку КВА>>Так ошибки не было Ну подумаеш два раза закрыли файл
K>Ошибка была.
КВА>>Для надежности
K>За такую "надежность" гнать надо тряпками, пропитанными известной жидкостью. Давайте еще для надежности два-три раза insert в sql делать — мало ли...
Ты наверное юмора не понимаеш? "Для надежности" это надо читать в кавычках
КВА>>>Вывод: реализация библиотеки ввода/вывода в Linux — кривовата ДД>>В данном случае реализация библиотеки критична к грубым ошибкам в приложении.
Пользуйтесь, например, stream'ом. Всяко проще.
кстати:
The behaviour of fclose() is undefined if the stream parameter is an
illegal pointer, or is a descriptor already passed to a previous invo-
cation of fclose().
(man 3 fclose)
Мне кажется, что под Solaris это Вам исключительно повезло, что оно не упало по SegFault. Потому как в любом случае free для структуры должен делаться. А два раза delete одного указателя... как оно на разных платформах (Solaris'а у меня под рукой, увы, нет, проверить не могу).
КВА>>Покатим бочку на Linux дальше КВА>>Это же как надо тупо реализовать библиотечные функции ввода/вывода КВА>>чтобы повторное закрытие файла ломало heap КВА>>кстати повторное закрытие файла в SUN, Windows ничего вредного не делает
ЧС> В Windows они ничего вредного не делают, потому что как я предполагаю, все эти функции реализованы через CreateFile(), CloseHandle(). А когда им передать неправильный хэндл, они его просто не находят в таблице открытых хэндлов и всё. В Линуксе наверно никаких таблиц нет, функция просто работает с указателем, считая ЧС>его правильным по умолчанию.
В Линуксе работа ведется так же через хендел, и его можно получить вызовом fileno
DESCRIPTION
...
[CX] [Option Start] The fclose() function shall mark for update the st_ctime and st_mtime fields of the underlying file, if the stream was writable, and if buffered data remains that has not yet been written to the file. The fclose() function shall perform the equivalent of a close() on the file descriptor that is associated with the stream pointed to by stream. [Option End]
... After the call to fclose(), any use of stream results in undefined behavior.
NAME
close — close a file descriptor
DESCRIPTION
The close() function shall deallocate the file descriptor indicated by fildes. To deallocate means to make the file descriptor available for return by subsequent calls to open() or other functions that allocate file descriptors. All outstanding record locks owned by the process on the file associated with the file descriptor shall be removed (that is, unlocked).
...
When all file descriptors associated with an open file description have been closed, the open file description shall be freed.
...
D>The behaviour of fclose() is undefined if the stream parameter is an
D>illegal pointer, or is a descriptor already passed to a previous invo-
D>cation of fclose().
D>(man 3 fclose)
D>Мне кажется, что под Solaris это Вам исключительно повезло, что оно не упало по SegFault. Потому как в любом случае free для структуры должен делаться. А два раза delete одного указателя... как оно на разных платформах (Solaris'а у меня под рукой, увы, нет, проверить не могу).
Вам не кажется, а Вы абсолютно правы, я цитировал IEEE Std 1003.1, 2004 (POSIX) здесь
On Mon, 12 Dec 2005 16:38:50 -0000, srggal <21794@users.rsdn.ru> wrote:
> ME>Что за критика такая? > > ME>В Linux ты не обрушишь kernel, он защищен от кривых рук, свое же приложение — пожалуйста. > > ЗАПРОСТО, в своём модуле, в контексте прерывания засну > И вот она ловещая паника ядра
Здравствуйте, MaximE, Вы писали:
ME>On Mon, 12 Dec 2005 16:38:50 -0000, srggal <21794@users.rsdn.ru> wrote:
>> ME>Что за критика такая? >> >> ME>В Linux ты не обрушишь kernel, он защищен от кривых рук, свое же приложение — пожалуйста. >> >> ЗАПРОСТО, в своём модуле, в контексте прерывания засну >> И вот она ловещая паника ядра
ME>Мы говорим про приложение, не про модуль ядра.
Дык просото к слову пришлось
ИМХО фраза пафосная про "не обрушишь kernel" вот и не сдержался, благо — дурацкое дело не хитрое, и сам, допустил подобный баг по неграмотности
D>>Мне кажется, что под Solaris это Вам исключительно повезло, что оно не упало по SegFault. Потому как в любом случае free для структуры должен делаться. А два раза delete одного указателя... как оно на разных платформах (Solaris'а у меня под рукой, увы, нет, проверить не могу).
S>Вам не кажется, а Вы абсолютно правы, я цитировал IEEE Std 1003.1, 2004 (POSIX) S>здесь
Здравствуйте, Alex Alexandrov, Вы писали:
AA>Здравствуйте, srggal, Вы писали:
ME>>>Мы говорим про приложение, не про модуль ядра.
S>>Дык просото к слову пришлось
S>>ИМХО фраза пафосная про "не обрушишь kernel" вот и не сдержался, благо — дурацкое дело не хитрое, и сам, допустил подобный баг по неграмотности
AA>Слава богу, модуль ядра нельзя загрузить из-под не-рута. А рутом систему можно изрушить и менее изощренными способами.
mr_jek wrote:
> Каждый вызов fclose это неявный вызов fflush в соотвествие со стандартом, > что случится при вызове fflush с невалидным указателем бог знает.
Ничего не должно произойти, если, конечно, fflush не скормить кривой
указатель (fflush использует fsync, который принимает файловый дескриптор,
а "плохие" дескрипторы обрабатываются).
> Да в стандарте предусмотрена "EBADF"
Только одна проблема, EBADF отдает close, а не fclose. Функции close
передается ИМЕННО ДЕСКРИПТОР, а не указатель на структуру, как в случае с
fclose. И, насколько я знаю, повторный вызов close для одного и того же
дескриптора совсем не страшен.
A>А подумать, прежде чем писать можно было? Ей передаётся не абы какой указатель, а выделенный fopen. Что мешает хранить где-то внутри список всех указателей выделенных fopen и при вызове fread, fwrite, fclose проверять валидность переданного указателя простым его вхождением в список?
Как Вы представляете работу какго-нибудь сервера собранного с такой библиотекой? Будет непрекращающаяся утечка памяти.
Здравствуйте, LelicDsp, Вы писали:
LD>Как Вы представляете работу какго-нибудь сервера собранного с такой библиотекой? Будет непрекращающаяся утечка памяти.
С какой стати? Надеюсь понятно, что внутри fclose указатель будет из списка удалятся?
A>А подумать, прежде чем писать можно было? Ей передаётся не абы какой указатель, а выделенный fopen. Что мешает хранить где-то внутри список всех указателей выделенных fopen и при вызове fread, fwrite, fclose проверять валидность переданного указателя простым его вхождением в список?
Кстати, я правильно понимаю, что аналогичную логику нужно будет реализовать в malloc/free, opendir/closedir, и еще в куче других функций, которые аллоцируют память?
On Thu, 15 Dec 2005 16:26:55 -0000, adontz <2053@users.rsdn.ru> wrote:
> C>В высшей степени странное утверждение! Функция glibc fclose соответствует > C>стандарту ANSI C, и в манах черным по белому написано, что ее поведение не > C>определено в случае передачи ей инвалидного указателя (что, кстати, > C>полностью соответствует стандарту). > > В данном случае соответсвие стандарту вряд ли можно назвать плюсом.
Лично меня такое поведение устраивает на 100%.
> C>Вообще непонятно, как ты хочешь обрабатывать передачу инвалидного УКАЗАТЕЛЯ функции, на нем что написано, что он кривой. > > А подумать, прежде чем писать можно было? Ей передаётся не абы какой указатель, а выделенный fopen. Что мешает хранить где-то внутри список всех указателей выделенных fopen и при вызове fread, fwrite, fclose проверять валидность переданного указателя простым его вхождением в список? Ничего не мешает, кроме лени и желания гнать понты. По сравнению со скоростью ввода-вывода это копейки.
Лишний footprint только для того, чтобы горстка наивных программистов не раздувала флейм в группах?
Я не хочу платить за то что не использую. Уверен, что большинство зрелых программистов думают также.
Разгребайте баги в своем коде специализированными тулзами, коих навалом бесплатно.
> Те же дескрипторы в Windows это сплошь указатели или индексы в таблицах, однако использование левого дескриптора не приводит ни к какому краху. UB на сегодня это плохой тон или детский сад, уж сам выбери.
Дескрипторы в Windows можно сравнивать с файловыми дескрипторами Unix, но не объектами FILE стандартной библиотеки.
Здравствуйте, LelicDsp, Вы писали:
LD>Кстати, я правильно понимаю, что аналогичную логику нужно будет реализовать в malloc/free, opendir/closedir, и еще в куче других функций, которые аллоцируют память?
opendir/closedir — да
malloc/free — есть более эффективные решения. Но да, суть та же. В Windows функция HeapFree с ума не сходит если ей передать мусор.
adontz wrote:
> В данном случае соответсвие стандарту вряд ли можно назвать плюсом.
)
> А подумать, прежде чем писать можно было? Ей передаётся не абы какой > указатель, а выделенный fopen. Что мешает хранить где-то внутри список > всех указателей выделенных fopen и при вызове fread, fwrite, fclose > проверять валидность переданного указателя простым его вхождением в > список? Ничего не мешает, кроме лени и желания гнать понты. По сравнению > со скоростью ввода-вывода это копейки. Те же дескрипторы в Windows это > сплошь указатели или индексы в таблицах, однако использование левого > дескриптора не приводит ни к какому краху. UB на сегодня это плохой тон > или детский сад, уж сам выбери.
"А подумать, прежде чем писать можно было?" ) Как по твоему должен
работать grep, который вынужден потенциально открывать ОООЧЕНЬ МНОГО
файлов? Eсли после выделения памяти для структуры FILE fopen'om, fclose не
будет освобождать эту память, то память будет "утекать". На 32-x битной
архитектуре sizeof(FILE) == 148, несложно подсчитать сколько потребуется
памяти для хранения FILE для УЖЕ ЗАКРЫТЫХ дескрипторов -- для 1000000 УЖЕ
ЗАКРЫТЫХ файлов потребуется 141 МБ (!), плюс для хранения указателей на
FILE 3 МБ, итого 144 МБ.
> Рекомендую думать, что говоришь и как говоришь. О того что кто-то в твойм > понимании пи@@ит твои слова не стали весомее, а мысли умнее."
LD>>Как Вы представляете работу какго-нибудь сервера собранного с такой библиотекой? Будет непрекращающаяся утечка памяти.
A>С какой стати? Надеюсь понятно, что внутри fclose указатель будет из списка удалятся?
Ок, согласен, можно было бы держать список валидных указателей. Стормозил. Но его придется делать потокобезопасным, делать для всех пар подобных функций... И чего добьемся в результате? Программы с трудные для отладки, с плохоповторяемым поведением...
Здравствуйте, MaximE, Вы писали:
ME>Лишний footprint только для того, чтобы горстка наивных программистов не раздувала флейм в группах?
Ты все свои программы написал без ошибок?
ME>Я не хочу платить за то что не использую. Уверен, что большинство зрелых программистов думают также.
Я не вижу чему тут сопротивлятся. Ну будет fclose что-то проверять в то время как ты будешь всегда передавать правильный указатель. И что?
ME>Разгребайте баги в своем коде специализированными тулзами, коих навалом бесплатно.
Максим, ты давно коммерческий софт разрабатывал? Релизы всегда выходят совсем безбажные?
Можно сколько угодно теоретизировать по поводу плохих программистов не умеющих отлаживать код, намекая при этом что ты сам не такой. На приктике же, подобная функциональность никого не стесняя может оказатся весьма полезной.
>> Те же дескрипторы в Windows это сплошь указатели или индексы в таблицах, однако использование левого дескриптора не приводит ни к какому краху. UB на сегодня это плохой тон или детский сад, уж сам выбери.
ME>Дескрипторы в Windows можно сравнивать с файловыми дескрипторами Unix, но не объектами FILE стандартной библиотеки.
Почему? Объяснишь великую разницу из-за которой возможное для дескрипторов, для указателей на FILE не выозможно.
Здравствуйте, LelicDsp, Вы писали:
LD>Но его придется делать потокобезопасным,
Это хорошо проработанная задача. Делается даже без блокировок.
LD>делать для всех пар подобных функций...
А их разве очень много? и потом, никто не говорил что дуракоустойчивую библиотеку написать так же легко.
LD>И чего добьемся в результате? Программы с трудные для отладки, с плохоповторяемым поведением...
Пояснишь? А то я не понял из чего ты сделал вывод о трудноотлаживаемости.
Здравствуйте, cattus, Вы писали:
C>"А подумать, прежде чем писать можно было?" ) Как по твоему должен C>работать grep, который вынужден потенциально открывать ОООЧЕНЬ МНОГО C>файлов? Eсли после выделения памяти для структуры FILE fopen'om, fclose не C>будет освобождать эту память, то память будет "утекать". На 32-x битной C>архитектуре sizeof(FILE) == 148, несложно подсчитать сколько потребуется C>памяти для хранения FILE для УЖЕ ЗАКРЫТЫХ дескрипторов -- для 1000000 УЖЕ C>ЗАКРЫТЫХ файлов потребуется 141 МБ (!), плюс для хранения указателей на C>FILE 3 МБ, итого 144 МБ.
Повторюсь специально для тебя. fclose удаляет указатель из списка валидных. Зачем хранить 1000000 значений указателей для УЖЕ ЗАКРЫТЫХ файлов я не очень понимаю.
On Thu, 15 Dec 2005 16:57:18 -0000, adontz <2053@users.rsdn.ru> wrote:
> Здравствуйте, MaximE, Вы писали: > > ME>Лишний footprint только для того, чтобы горстка наивных программистов не раздувала флейм в группах? > > Ты все свои программы написал без ошибок?
Я обычный человек, нам свойственно ошибаться
> ME>Я не хочу платить за то что не использую. Уверен, что большинство зрелых программистов думают также. > > Я не вижу чему тут сопротивлятся. Ну будет fclose что-то проверять в то время как ты будешь всегда передавать правильный указатель. И что?
memory footprint, мобильные ус-ва приходят тут же на ум. Просто вот так (шелчок пальцами) все приложения, которые используют FILE* будут больше кушать памяти?
> ME>Разгребайте баги в своем коде специализированными тулзами, коих навалом бесплатно. > > Максим, ты давно коммерческий софт разрабатывал? Релизы всегда выходят совсем безбажные?
Релизы бывают без критических багов. Но это уже разглагольствование — баги могут быть везде.
> Можно сколько угодно теоретизировать по поводу плохих программистов не умеющих отлаживать код, намекая при этом что ты сам не такой. На приктике же, подобная функциональность никого не стесняя может оказатся весьма полезной.
Тулзы есть для этого. Мне такой функционал нафиг не нужон.
>>> Те же дескрипторы в Windows это сплошь указатели или индексы в таблицах, однако использование левого дескриптора не приводит ни к какому краху. UB на сегодня это плохой тон или детский сад, уж сам выбери. > > ME>Дескрипторы в Windows можно сравнивать с файловыми дескрипторами Unix, но не объектами FILE стандартной библиотеки. > > Почему? Объяснишь великую разницу из-за которой возможное для дескрипторов, для указателей на FILE не выозможно.
HANDLE и файловый дескриптор ссылаются на стр-ры/объекты ядра. FILE* — на объект из user mode библиотеки.
Здравствуйте, MaximE, Вы писали:
ME>memory footprint, мобильные ус-ва приходят тут же на ум. Просто вот так (шелчок пальцами) все приложения, которые используют FILE* будут больше кушать памяти?
Реализация несколих списков да и сами списки вряд ли займут сущесвенное количество памяти. Если ты отроешь 250 файлов и будешь хранить валидные указатели в виде RB дерева (чтобы быстрее искать), то на 32битной платформе получишь (3 указателя + 1 указатель) * sizeof(void *) * 250 = 4000 байт данных. ИМХО даже для мобильных устройств это совершенно смешной объём
ME>Тулзы есть для этого. Мне такой функционал нафиг не нужон.
Устойчивые ошибки и так отладить можно. Ресь о появляющихся иногда. Тут тулзы не особо помогут. Даже unit-testing.
ME>HANDLE и файловый дескриптор ссылаются на стр-ры/объекты ядра. FILE* — на объект из user mode библиотеки.
Если честно, всё равно не понимаю. или ты о чём-то специфичном для linux?
Здравствуйте, cattus, Вы писали:
C>И, насколько я знаю, повторный вызов close для одного и того же C>дескриптора совсем не страшен.
Страшен. Особенно отсутствием реакции. Ибо может привести к закрытию не того дескриптора, что совсем неприятно. Одним словом, такого быть не должно. Равно как и повторных вызовов free() на уже освобожденную память, например. Подобные вещи приводят часто к трудно воспроизводимым ошибкам.
Здравствуйте, adontz, Вы писали:
ME>>memory footprint, мобильные ус-ва приходят тут же на ум. Просто вот так (шелчок пальцами) все приложения, которые используют FILE* будут больше кушать памяти? A>Реализация несколих списков да и сами списки вряд ли займут сущесвенное количество памяти. Если ты отроешь 250 файлов и будешь хранить валидные указатели в виде RB дерева (чтобы быстрее искать), то на 32битной платформе получишь (3 указателя + 1 указатель) * sizeof(void *) * 250 = 4000 байт данных. ИМХО даже для мобильных устройств это совершенно смешной объём
Расскажите об этом разработчикам встроенных систем всякого рода. Вы их осчастливите запасом хорошего настроения на день. От хохота.
ME>>Тулзы есть для этого. Мне такой функционал нафиг не нужон. A>Устойчивые ошибки и так отладить можно. Ресь о появляющихся иногда. Тут тулзы не особо помогут. Даже unit-testing.
Эх, барин, жениться вам пора... Тьфу, тестеров нанять. Которые будут в том числе отслеживать code coverage тестами. Ну и valgrind в зубы, для кумплекту. А то так и утечки памяти спишете на "кривую реализацию".
LD>>Но его придется делать потокобезопасным, A>Это хорошо проработанная задача. Делается даже без блокировок.
Верится с трудом.
LD>>делать для всех пар подобных функций... A>А их разве очень много? и потом, никто не говорил что дуракоустойчивую библиотеку написать так же легко.
Дело не в сложно/несложно. Не сложнее чем компилятор. Непонятно зачем это нужно.
LD>>И чего добьемся в результате? Программы с трудные для отладки, с плохоповторяемым поведением... A>Пояснишь? А то я не понял из чего ты сделал вывод о трудноотлаживаемости.
Исключительно из опыта. Замаскированная ошибка может выявиться на очень поздних стадиях разработки. А стоимость отладки и устранения ошибок возрастает очень быстро при удалении от начала разработки.
Чтобы приложение не падало. Пусть себе пишет в log файл что была попытка закрыть несуществуещий дескриптор. Скажешь не лучше?
LD>Исключительно из опыта. Замаскированная ошибка может выявиться на очень поздних стадиях разработки. А стоимость отладки и устранения ошибок возрастает очень быстро при удалении от начала разработки.
Надо анализировать как прошло выполнение fclose и если была ошибка логгировать её. Я по лог-айлам отлаживал программу на компьютере к ткоторому не имел доступа. Искажу прямо — очень было удобно. Со всякими Watch/Breakpoint было бы намного хуже.
Здравствуйте, Kemm, Вы писали:
K>Когда и unix-like ОС начнут действовать по принципу M$^H^H "если наши функции не соответствуют стандарту — тем хуже для стандарта", то я уже даже и не знаю, куды бечь надо будет. В другую вселенную, не иначе.
В данном случае расширение касается Undefined Behavior и я не понимаю по какому поводу паника? Вай-вай-вай, где же мой UB?
K>Детский сад — это писать код, не соответствующий стандарту. Мне куда дороже более быстрое выполнение (даже если это 1 процент, хотя может быть значительно больше в Вашем случае), чем детские ошибки. gcov + valgrind творят чудеса, к сведению.
Детский сад это думать что кто-то намеренно пишет такой код. Лог файлы на клиентских машинах творят куда бОльшие чудеса, чем любые утилитки на машине разработчика. Пиши в логи всякий раз когда fclose будет вызвана не к месту. Тебе информация к размышлению, клиенту программа которая не валится. Религия не позволяет использовать или как?
Здравствуйте, Kemm, Вы писали:
K>Расскажите об этом разработчикам встроенных систем всякого рода. Вы их осчастливите запасом хорошего настроения на день. От хохота.
Вот я на днях буду для смартфона писать. На .Net Compact Framework. Ну думаю понятно
K>Тьфу, тестеров нанять. Которые будут в том числе отслеживать code coverage тестами. Ну и valgrind в зубы, для кумплекту. А то так и утечки памяти спишете на "кривую реализацию".
Лог-файлы обойдудтся дешевле команды тестеров, а информации при должном использовании дадут больше.
Здравствуйте, adontz, Вы писали:
K>>Когда и unix-like ОС начнут действовать по принципу M$^H^H "если наши функции не соответствуют стандарту — тем хуже для стандарта", то я уже даже и не знаю, куды бечь надо будет. В другую вселенную, не иначе. A>В данном случае расширение касается Undefined Behavior и я не понимаю по какому поводу паника? Вай-вай-вай, где же мой UB?
Нет. Вай-вай-вай, какого черта вот в этом вот месте этот трижды проклятый someOS не соответствует стандарту? А, решили, что можно произвольно реализовывать все, а не только UB...
K>>Детский сад — это писать код, не соответствующий стандарту. Мне куда дороже более быстрое выполнение (даже если это 1 процент, хотя может быть значительно больше в Вашем случае), чем детские ошибки. gcov + valgrind творят чудеса, к сведению. A>Детский сад это думать что кто-то намеренно пишет такой код.
Еще раз: Тестировать надо. Во всех позах. С использованием утилит, показывающих покрытие исходного текста тестами.
A>Лог файлы на клиентских машинах творят куда бОльшие чудеса, чем любые утилитки на машине разработчика. Пиши в логи всякий раз когда fclose будет вызвана не к месту.
my_fopen()/my_fclose() в помощь, если уж приспичило. Да, а еще покажите мне, как логировать, чтобы отслеживать пресловутые memory leaks, раз уж Вы так утилиты на машинах разработчиков и тестеров не любите.
A>Тебе информация к размышлению, клиенту программа которая не валится. Религия не позволяет использовать или как?
Религия мне не позволяет считать свое видение проблемы единственно верным. И пока есть реализации, не соответствующие ему — кричать на всю ивановскую "кривизна".
LD>>Верится с трудом. A>http://www.google.com/search?q=lock+free+list
Лень углубляться посмотрел несколько первых ссылок. Нигде настоящего lock-free списка не релиизована. Везде основываются на атомарность compare-and-swap. Ниже типичная цитата. Подавляющее большинство аппаратных архитектур такой роскоши не имеют.
Prior list-based lock-free set algorithms involve one or more
serious problems: dependence on the DCAS (double-compareand-
swap)1 atomic primitive that is not supported on any
current processor architecture [5, 14], susceptibility to livelock
[25], and/or dependence on problematic memory management
methods [6, 14, 25] (i.e., memory management methods
that are impractical, very inefficient, blocking (not lockfree),
and/or dependent on special operating system support).
The use of universal lock-free methodologies [1, 2, 8, 11,
22, 24] for implementing hash tables or sets in general is too
inefficient to be practical.
This paper presents a lock-free list-based set algorithm that
we use as a building block of a lock-free hash table algorithm.
The algorithm is dynamic, allowing the object size
and memory use to grow and shrink arbitrarily. It satisfies
the linearizability correctness condition [9].
It uses CAS (compare-and-swap) or equivalently restricted
LL/SC (load-linked/store-conditional)
LD>>Дело не в сложно/несложно. Не сложнее чем компилятор. Непонятно зачем это нужно. A>Чтобы приложение не падало. Пусть себе пишет в log файл что была попытка закрыть несуществуещий дескриптор. Скажешь не лучше?
Лучше конечно, никаких сомнений даже быть не может. Только как это сделать? Чтоб всех устроило.
K>>Тьфу, тестеров нанять. Которые будут в том числе отслеживать code coverage тестами. Ну и valgrind в зубы, для кумплекту. А то так и утечки памяти спишете на "кривую реализацию".
A>Лог-файлы обойдудтся дешевле команды тестеров, а информации при должном использовании дадут больше.
Очень может быть, но причем тут стандартная либа?
Здравствуйте, Kemm, Вы писали:
K>Напиши обертку вокруг fopen()/fclose(), которая этим будет заниматься. Медленнее не будет, зато будет правильно. А то в лог писать... В какой лог, простите?..
Да хоть в файл. Хотя БД конечно лучше, но просто не всегда есть.
K>>Напиши обертку вокруг fopen()/fclose(), которая этим будет заниматься. Медленнее не будет, зато будет правильно. А то в лог писать... В какой лог, простите?..
A>Да хоть в файл. Хотя БД конечно лучше, но просто не всегда есть.
Здравствуйте, adontz, Вы писали:
K>>Расскажите об этом разработчикам встроенных систем всякого рода. Вы их осчастливите запасом хорошего настроения на день. От хохота. A>Вот я на днях буду для смартфона писать. На .Net Compact Framework. Ну думаю понятно
Вы-таки удивитесь, но встроенные системы — это не только смартфоны/КПК и прочие фоны. Да и вообще не они. 8))
K>>Тьфу, тестеров нанять. Которые будут в том числе отслеживать code coverage тестами. Ну и valgrind в зубы, для кумплекту. А то так и утечки памяти спишете на "кривую реализацию". A>Лог-файлы обойдудтся дешевле команды тестеров, а информации при должном использовании дадут больше.
А Вы не подскажете компанию, в которой принят такой подход? Чтоб не купить ничего ненароком...
Было у нас раньше примерно так же, по вине руководства, которое к программированию имело примерно столько же отношения, сколько я к ядерной энергетике. Кончилось, когда жареный петух клюнул и "дело запахло вазелином"(с). До сих пор вспоминаем эту эпохальную фразу начальника: "Зачем нам тестеры? И так все нормально...". С какими мыслями вспоминаем, приводить не буду по цензурным соображениям. До сих пор нормальное тестирование построить не можем, хотя легче стало намного.
Да, ценность логов отрицать я не собираюсь, это просто-напросто глупо. Только не являются они серебряной пулей ни разу. Просто один из равноправных инструментов.
Здравствуйте, LelicDsp, Вы писали:
LD>>>Верится с трудом. A>>http://www.google.com/search?q=lock+free+list LD>Лень углубляться посмотрел несколько первых ссылок. Нигде настоящего lock-free списка не релиизована. Везде основываются на атомарность compare-and-swap. Ниже типичная цитата. Подавляющее большинство аппаратных архитектур такой роскоши не имеют.
Проблемы не увидел. Для x86 это одна команда процессора. Обменять по условию 1, 2, 4 байт — CMPXCHG (поддерживается начиная c 486), 8 байт CMPXCHG8B (поддерживается начиная c Pentium I)
Здравствуйте, Kemm, Вы писали:
K>Нет. Вай-вай-вай, какого черта вот в этом вот месте этот трижды проклятый someOS не соответствует стандарту? А, решили, что можно произвольно реализовывать все, а не только UB...
Я говорил только об UB.
K>Религия мне не позволяет считать свое видение проблемы единственно верным. И пока есть реализации, не соответствующие ему — кричать на всю ивановскую "кривизна".
Пока что ты борешься за реализацию с никому не нужным UB.
Здравствуйте, Kemm, Вы писали:
K>Вы-таки удивитесь, но встроенные системы — это не только смартфоны/КПК и прочие фоны. Да и вообще не они. 8))
Я и не предлагал втыкать кучу run-time проверок на девайсы с 32Кб памяти.
K>А Вы не подскажете компанию, в которой принят такой подход? Чтоб не купить ничего ненароком... K>Было у нас раньше примерно так же, по вине руководства, которое к программированию имело примерно столько же отношения, сколько я к ядерной энергетике. Кончилось, когда жареный петух клюнул и "дело запахло вазелином"(с). До сих пор вспоминаем эту эпохальную фразу начальника: "Зачем нам тестеры? И так все нормально...". С какими мыслями вспоминаем, приводить не буду по цензурным соображениям. До сих пор нормальное тестирование построить не можем, хотя легче стало намного. K>Да, ценность логов отрицать я не собираюсь, это просто-напросто глупо. Только не являются они серебряной пулей ни разу. Просто один из равноправных инструментов.
Я и не говорил, давайте вообще без тестеров. Я просто имею ввиду, что есть оишбки, которые никакие тестеры не поумают, потому что они только на том треклятом компьютере и проявляются. И тестеры тоже не являются серебряной пулей, сколько бы их не было. Более того, я регулярно пишу код который отклоняется от того или иного стандарта, зато совместим с существующим ПО, которое тоже отклоняется. Тут уже любые тестеры идут лесом — отладка только по логам.
Здравствуйте, adontz, Вы писали:
K>>Нет. Вай-вай-вай, какого черта вот в этом вот месте этот трижды проклятый someOS не соответствует стандарту? А, решили, что можно произвольно реализовывать все, а не только UB... A>Я говорил только об UB.
Следом было предложение писать из библотечной функции логи. Вот уже прямое несоответствие стандарту.
K>>Религия мне не позволяет считать свое видение проблемы единственно верным. И пока есть реализации, не соответствующие ему — кричать на всю ивановскую "кривизна". A>Пока что ты борешься за реализацию с никому не нужным UB.
Пока я борюсь за отсутствие необходимости усложнять. По мне, ошибка вылезшая в момент возникновения лучше ошибки, вылезшей через 5 минут. Проще оно в поимке и отладке. И, хотя второй fclose() приводит к SIGSEGV'у на нелюбимом мной линуксе, а на более приятных для меня ОС не приводит, я склоняюсь в пользу линуксовой реализации именно по этой причине.
Здравствуйте, adontz, Вы писали:
K>>Вы-таки удивитесь, но встроенные системы — это не только смартфоны/КПК и прочие фоны. Да и вообще не они. 8)) A>Я и не предлагал втыкать кучу run-time проверок на девайсы с 32Кб памяти.
Так. А как себя на этих девайсах должен вести fclose() в таком случае?.. Или мы в стандарте оставляем по старому, но гнобим всех, кто UB реализовал без проверок?
K>>Было у нас раньше примерно так же, по вине руководства, которое к программированию имело примерно столько же отношения, сколько я к ядерной энергетике. Кончилось, когда жареный петух клюнул и "дело запахло вазелином"(с). До сих пор вспоминаем эту эпохальную фразу начальника: "Зачем нам тестеры? И так все нормально...". С какими мыслями вспоминаем, приводить не буду по цензурным соображениям. До сих пор нормальное тестирование построить не можем, хотя легче стало намного. K>>Да, ценность логов отрицать я не собираюсь, это просто-напросто глупо. Только не являются они серебряной пулей ни разу. Просто один из равноправных инструментов. A>Я и не говорил, давайте вообще без тестеров. Я просто имею ввиду, что есть оишбки, которые никакие тестеры не поумают, потому что они только на том треклятом компьютере и проявляются. И тестеры тоже не являются серебряной пулей, сколько бы их не было. Более того, я регулярно пишу код который отклоняется от того или иного стандарта, зато совместим с существующим ПО, которое тоже отклоняется. Тут уже любые тестеры идут лесом — отладка только по логам.
Неоттестированный продукт продуктом не является. (с) Так что без тестеров идет лесом скорее такой "продукт".
Вы можете мне объяснить, чем вам не нравятся обертки вокруг f*()?
Здравствуйте, adontz, Вы писали:
LD>>>>Верится с трудом. A>>>http://www.google.com/search?q=lock+free+list LD>>Лень углубляться посмотрел несколько первых ссылок. Нигде настоящего lock-free списка не релиизована. Везде основываются на атомарность compare-and-swap. Ниже типичная цитата. Подавляющее большинство аппаратных архитектур такой роскоши не имеют. A>Проблемы не увидел. Для x86 это одна команда процессора. Обменять по условию 1, 2, 4 байт — CMPXCHG (поддерживается начиная c 486), 8 байт CMPXCHG8B (поддерживается начиная c Pentium I)
Hint: i86 не самое популярное семейство процессоров.
Здравствуйте, Kemm, Вы писали:
K>Следом было предложение писать из библотечной функции логи. Вот уже прямое несоответствие стандарту.
Где я такое сказал?
if(fclose(file) == EOF) log("what the f...?");
Ты сперва придумываешь за меня что-то, а потом доблесно с этим сражаешься. Зачем?
Здравствуйте, adontz, Вы писали:
K>>Следом было предложение писать из библотечной функции логи. Вот уже прямое несоответствие стандарту. A>Где я такое сказал? A>
A>if(fclose(file) == EOF) log("what the f...?");
A>
A>Ты сперва придумываешь за меня что-то, а потом доблесно с этим сражаешься. Зачем?
Тогда так и надо говорить, говорили-то про libc. Это разумно. Следующий шаг:
int
my_fclose(FILE *file)
{
if (!is_valid_file(file)) {
log("Attempt to close closed file");
return(EBADF);
}
delete_from_valid_files(file);
return fclose(file);
}
FILE *
my_fopen(const char *path, const char *mode)
{
FILE *file;
if ((file = fopen(path, mode)) != NULL) {
add_valid_file(file);
return file;
}
return NULL;
}
Чем это-то хуже, например? Благо, можно просто через LD_PRELOAD подсунуть обертку на fopen()/fclose(), если софт в бинарный...
Здравствуйте, Kemm, Вы писали:
K>Так. А как себя на этих девайсах должен вести fclose() в таком случае?.. Или мы в стандарте оставляем по старому, но гнобим всех, кто UB реализовал без проверок?
Честно говоря я себе очень слабо представляю какой F надо CLOSE если у тебя всего 32Кб. В любом случае разработка программ под такие устройства это совсем другой стиль.
K>Вы можете мне объяснить, чем вам не нравятся обертки вокруг f*()?
Ничем. Почти. Их надо таскать за собой из проекта в проект, когда можно было бы реализовать на уровне LIBC.
Здравствуйте, Kemm, Вы писали:
K>Hint: i86 не самое популярное семейство процессоров.
Не самое популярное где? Тогда уж назови самое популярное. Кстати позаботься, чтобы у самого популярного по твоей версии семейства не было аналога команды CMPXCHG
Здравствуйте, adontz, Вы писали:
K>>Hint: i86 не самое популярное семейство процессоров. A>Не самое популярное где? Тогда уж назови самое популярное. Кстати позаботься, чтобы у самого популярного по твоей версии семейства не было аналога команды CMPXCHG
Чтоб я помнил все ассемблеры. Мне достаточно того, что на ряде платформ нет. На arm'е есть? На sparc'е? По-моему, ни там, ни там.
Здравствуйте, adontz, Вы писали:
K>>Так. А как себя на этих девайсах должен вести fclose() в таком случае?.. Или мы в стандарте оставляем по старому, но гнобим всех, кто UB реализовал без проверок? A>Честно говоря я себе очень слабо представляю какой F надо CLOSE если у тебя всего 32Кб.
У-у-у... Про спектрумы уже и забыли... 8))
A>В любом случае разработка программ под такие устройства это совсем другой стиль.
И что? Будем два стандарта С держать?
K>>Вы можете мне объяснить, чем вам не нравятся обертки вокруг f*()? A>Ничем. Почти. Их надо таскать за собой из проекта в проект, когда можно было бы реализовать на уровне LIBC.
Хм... Великий труд — таскать с собой библиотечку из N функций... В любом случае, я вот как минимум всегда с собой таскаю реализацию strlcpy()/strlcat() из, afair, NetBSD. Просто потому, что это удобно.
А вот возражения против обязательной проверки в рамках libc уже озвучили, и не одно.
Здравствуйте, Kemm, Вы писали:
K>Чтоб я помнил все ассемблеры. Мне достаточно того, что на ряде платформ нет. На arm'е есть? На sparc'е? По-моему, ни там, ни там.
Как тут же заметили список уже есть. Осталось им только воспользоватся.
Здравствуйте, Pzz, Вы писали:
>> LD>>Но его придется делать потокобезопасным, >> A>Это хорошо проработанная задача. Делается даже без блокировок. >> Ну-ка, ну-ка... Потокобезопасную реализацию fopen() со списком валидных >> 'FILE *' в студию.
Pzz>Строго говоря, в любой реализации этот список уже есть. Hint: exit() Pzz>обязана закрыть все файлы, открытые через fopen(). И при этом не забыть Pzz>сказать на них fflush().
Она обязана закрыть вообще все открытые файлы, не важно. Мне куда более в этот момент интересна переносимая реализация потокобезопасного fopen() со списком валидных файлов, не использующая блокировок. 8))
Pzz>Но тем не менее, это не значит, что fclose() _обязан_ проверять файл на Pzz>валидность.
Здравствуйте, Pzz, Вы писали:
Pzz>3) Стиль языка C заключается, в частности, в том, что библиотека и компилятор доверяют программисту. Сказали fclose() два раза, значит будем закрывать файл два раза. Сказали поделить на ноль, значит будем делить на ноль. Для тех, кто не согласен с такой политикой, существуют "безопасные" языки программирования. Там все, что надо, проверяется. Pzz>Платой за удобства обычно является потеря эффективности.
Я как бы не очень понял, почему политика библиотеки LIBC это свойство языка С и почему нельзя внести обсуждаемое изменение, если оно никак не влияет на существующие программы и не мешает диагностировать ошибки (они скрываются, просто больше не приводят к фатальным последствиям).
Я не прошу изменить стандарт, я спрашиваю чем это было бы плохо? Да можно это сделать и в виде обёрток, но как оказалось список уже есть, так зачем строить второй, когда уже есть готовый?
Здравствуйте, Kemm, Вы писали:
K>И что? Будем два стандарта С держать?
Я стандарт менять не собирался
K>Хм... Великий труд — таскать с собой библиотечку из N функций... В любом случае, я вот как минимум всегда с собой таскаю реализацию strlcpy()/strlcat() из, afair, NetBSD. Просто потому, что это удобно.
Как тут заметили список уже есть. Если писать обёртки, то мы зачем-то будет иметь два списка.
K>А вот возражения против обязательной проверки в рамках libc уже озвучили, и не одно.
Это когда вы думали, что я из библиотечно функции буду в логи писать. Или я что-то упустил?
Здравствуйте, Kemm, Вы писали:
K>Она обязана закрыть вообще все открытые файлы, не важно. Мне куда более в этот момент интересна переносимая реализация потокобезопасного fopen() со списком валидных файлов, не использующая блокировок. 8))
Полностью переносимой конечно же нет. На каких-то процессорах потребуются блокировки.
Pzz>>Но тем не менее, это не значит, что fclose() _обязан_ проверять файл на валидность. K>Угу. Что и пытаемся доказать.
Я и не говорю, что объязан. Я говорю — было бы очень неплохо.
Здравствуйте, adontz, Вы писали:
K>>Она обязана закрыть вообще все открытые файлы, не важно. Мне куда более в этот момент интересна переносимая реализация потокобезопасного fopen() со списком валидных файлов, не использующая блокировок. 8)) A>Полностью переносимой конечно же нет. На каких-то процессорах потребуются блокировки.
Именно поэтому не интересно.
Pzz>>>Но тем не менее, это не значит, что fclose() _обязан_ проверять файл на валидность. K>>Угу. Что и пытаемся доказать. A>Я и не говорю, что объязан. Я говорю — было бы очень неплохо.
Ну так было бы неплохо, например, иметь strlcpy()/strlcat() везде. "Везде" включает в себя стандарт. Так же было бы неплохо иметь там же [v]asprintf(). Ну так я же не называю системы, где нет перечисленного, кривыми в плане реализации libc?
Здравствуйте, Kemm, Вы писали:
K>Ну так было бы неплохо, например, иметь strlcpy()/strlcat() везде. "Везде" включает в себя стандарт. Так же было бы неплохо иметь там же [v]asprintf(). Ну так я же не называю системы, где нет перечисленного, кривыми в плане реализации libc?
Если ты не заметил, то я отвечал на это
В высшей степени странное утверждение! Функция glibc fclose соответствует стандарту ANSI C, и в манах черным по белому написано, что ее поведение не определено в случае передачи ей инвалидного указателя (что, кстати, полностью соответствует стандарту).
Вообще непонятно, как ты хочешь обрабатывать передачу инвалидного УКАЗАТЕЛЯ функции, на нем что написано, что он кривой.
И просто показал, что функция никак не противореча стандарту может устойчиво распознавать невалидные указатели. Вот и всё. А то что LIBC кривая, это ты меня с кем-то перепутал.
Здравствуйте, 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 и т.д.?
А почему нет? Идеология не позволяет?
ДД>Для быстрой и дешевой разработки ПО, некритичного к кривости рук программиста, существуют соответствующие технологии и языки.
Кривизна рук тут ни при чём. Ошибки делают все. Я не очень понимаю, зачем надо гордится тем, что "язык на котором я программирую позволяет совершать более изощерённые ошибки" и тем более лелеять это как святыню.
Здравствуйте, adontz, Вы писали:
ДД>>Для быстрой и дешевой разработки ПО, некритичного к кривости рук программиста, существуют соответствующие технологии и языки. A>Кривизна рук тут ни при чём. Ошибки делают все. Я не очень понимаю, зачем надо гордится тем, что "язык на котором я программирую позволяет совершать более изощерённые ошибки" и тем более лелеять это как святыню.
Потому что это, может быть, и приводит к более "изощренным" (а если уж быть честным — глупым) шибкам, но позволяет в массе своей избежать ошибок, причина которых возникла полгода назад во время исполнения софта.
Здравствуйте, MaximE, Вы писали:
>> Раз они юзают malloc, free то пусть будут добры не попадать в условия когда >> портится heap (например повторное закрытие файла)
ME>Лучше пусть они маскируют ошибки в твоем коде, так?
Маскируют ? Если бы во время повторного закрытия валился аналог Debug Break, это было бы неплохо, а так валится хип. Увидел программист, что хип повалился, что ему дальше делать ?
Здравствуйте, pavel_turbin, Вы писали:
КВА>>А возмутило меня другое Анализ лога valgrind показал что библиотечные КВА>>функции fprintf, fclose вовсю юзают malloc, free
_>а вы думаете под Windows API функции не используют HeapAlloc? вы ошибаетесь. Однако, если память не выделена, CreateFile обломится.
Все правильно, только дескриптор закрывай сколько хочешь, худа от этого не будет. Тебе вернется код ошибки и все.
Tanker wrote: > Все правильно, только дескриптор закрывай сколько хочешь, худа от этого > не будет. Тебе вернется код ошибки и все.
Ошибаетесь.
Во-первых, дескриптор внутри себя ведет счетчик ссылок. Соответственно,
при лишнем закрытии может полететь другой код, который использует этот
дескриптор.
Во-вторых, количество номеров дескрипторов — конечно. И в интервале
между закрытиями дескриптора может быть создан еще один
дескриптор с совпадающим номером.
Здравствуйте, Cyberax, Вы писали:
C>Во-первых, дескриптор внутри себя ведет счетчик ссылок. Соответственно, при лишнем закрытии может полететь другой код, который использует этот дескриптор.
Это детали и особенности реализации конкретных дескрипторов.
C>Во-вторых, количество номеров дескрипторов — конечно.
+1
C>И в интервале между закрытиями дескриптора может быть создан еще один дескриптор с совпадающим номером.
Это никак не мешает отслеживать ошибку. Правда она обнаружится немного позже, но это всё таки лучше чем вылящееся приложение.
adontz wrote: > C>Во-первых, дескриптор внутри себя ведет счетчик ссылок. > Соответственно, при лишнем закрытии может полететь другой код, который > использует этот дескриптор. > Это детали и особенности реализации конкретных дескрипторов.
Ну как бы это не отменяет ошибок, которые могут быть получены из-за этого.
> C>И в интервале между закрытиями дескриптора может быть создан *еще > один* дескриптор с совпадающим номером. > Это никак не мешает отслеживать ошибку. Правда она обнаружится немного > позже, но это всё таки лучше чем вылящееся приложение.
Во время отладки такая ошибка элементарно обнаруживается по backtrace'у
из fclose.
adontz wrote:
> Здравствуйте, ДимДимыч, Вы писали: > > ДД>Может. Не спорю. Но нужно ли это? В некоторых случаях, таких как > отладка — нужно. Для этого есть glibc-debug, например, которая проверяет > валидность указателей, реализация собственных оберток и т.д. В остальных > случаях — не нужно, потому как: 1) неразумно используется память и > процессорное время; 2) это способствует распространению некачественного > кода и таких же программистов. > > Память не будет неразумно использоватся, потому что список и так уже есть. > Процессорное время да — но поиск в списке из нескольких десятков элементов > мелочи по сравнению со скоростью ввода-вывода. > > Дело в том что в релизе тоже есть ошибки, но там glibc-debug не > используют. И ИМХО лучше если библиотека вернёт тебе некоторый код ошибки, > который будет обработан, чем если приложение просто рухнет. Лучше не для > тебя (dump был бы весьма полезен), а для конечного пользователя. Заметь в > первом сообщении речь шла о программе, которую портировали. То есть > когда-то её написали и она работала себе и работала с этой ошибкой, но > потом её решили портировать и версия LIBC на новой платформе уже от старой > ошибки рушит программу. Так что рассуждать о том, что мол "не надо два > раза закрывать файл" это конечно хорошо, но к реальности не имеет > отношения. Бывает, что и закрывают. И я бы предпочёл, что бы такие вещи из > разряда error перешли в warning. На самом деле мои слова тоже на ветер. > LIBC никто не препишет, стандарт не изменят, а файлы будут по прежнему > закрывать по два раза.
C>Во-первых, дескриптор внутри себя ведет счетчик ссылок. Соответственно, C>при лишнем закрытии может полететь другой код, который использует этот C>дескриптор.
Здравствуйте, Pzz, Вы писали:
Pzz>pavel_turbin wrote: >> >> я обычно проверяю что венул close >> типа >> >> ret = CloseHanlde(h); >> assert(ret);
Pzz>А UNIX'овский close() Вы тоже будете проверять assert'ом?
почему бы и нет?
int close(int fildes);
RETURN VALUES
Upon successful completion, 0 is returned. Otherwise, -1 is
returned and errno is set to indicate the error.
ERRORS
ret = close(fd);
assert( ret == 0 );
ret = close(fd);
assert( ret == 0 ); // должен сработать
Здравствуйте, Pzz, Вы писали:
Pzz>close() может вернуть -1 по внешним причинам. Например, из-за того, что Pzz>не удалось отлить на диск отложенную запись.
Pzz>Разве тот факт, что на диске кончилось место, может считаться Pzz>уважительной причиной упасть по assert'у?
естественно, если вы обрабатываете специальным образом ошибку из close, например, повторяете вызов через несколько секунд, то assert не нужен. НО если вы просто игнорируете его код возврата:
int myfunction()
{
int fh = open(...);
if( fh < 0 )
return -1;
read(...);
close(fh); // часто можно видет такой кодreturn 0;
}
то хорошо бы и хотя бы про-assert-ить.
Еще один момент, я обычно сохраняю assert-ы в релизе. Они пишут в error-log, тогда можно было отследить ошибки и в release.
pavel_turbin wrote: > > Pzz>Разве тот факт, что на диске кончилось место, может считаться > Pzz>уважительной причиной упасть по assert'у? > > естественно, если вы обрабатываете специальным образом ошибку из close, > например, повторяете вызов через несколько секунд, то assert не нужен.
К сожалению, close(), это навсегда. Даже если Вы получили -1, дескриптор
уже закрыт.
> НО если вы просто игнорируете его код возврата: > > int myfunction() > { > int fh = open(...); > if( fh < 0 ) > return -1; > > read(...); > > close(fh); // часто можно видет такой код > return 0; > }
Можно еще сознательно игнорировать результат close(). Например, если я
закрываю временный файл, который уже отслужил свое, зачем мне знать код
возврата? Сделать-то с ним ничего осмысленного я все равно не смогу...
Кстати, и в приведенном Вами примере, ну какая Вам разница, чем кончился
close, если Вы прочли то, что собирались? Если он кончился чем-то не
тем, это (в данном случае, не вообще!) уже проблема системы, а не Ваша.
> Еще один момент, я обычно сохраняю assert-ы в релизе. Они пишут в > error-log, тогда можно было отследить ошибки и в release.
Я тоже сохраняю. Но еще раз, assert это для _внутренних_ ошибок в
программе. Внешние ошибки 1) должны обрабатываться, кроме тех случаев,
когда факт возможной ошибки _сознательно_ игнорируется 2) должны
обрабатываться по-другому, чем внутренние.
Здравствуйте, Pzz, Вы писали:
Pzz>pavel_turbin wrote:
Pzz>Можно еще сознательно игнорировать результат close(). Например, если я Pzz>закрываю временный файл, который уже отслужил свое, зачем мне знать код Pzz>возврата? Сделать-то с ним ничего осмысленного я все равно не смогу...
тут в другом дело. Задача избежать 2-го закрытия того же handle-a. handle может принять значение какого-нибудь уже существующего handle-a, т.к после close его значение может быть вновь использовано.
в multy-thread приложении (и не только!) 2-ое закрытие иногда может быть успешным, т.к. старое значение fh может случайно совпасть с только что открытым новым файлом в параллельном потоке. assert от результата close помогает найти такие ошибки.
pavel_turbin wrote: > > Pzz>Можно еще сознательно игнорировать результат close(). Например, если я > Pzz>закрываю временный файл, который уже отслужил свое, зачем мне знать код > Pzz>возврата? Сделать-то с ним ничего осмысленного я все равно не смогу... > > тут в другом дело. Задача избежать 2-го закрытия того же handle-a. > handle может принять значение какого-нибудь уже существующего handle-a, > т.к после close его значение может быть вновь использовано.
Ну, на все случаи жизни соломки не подстелишь. Причем Вы, ради борьбы с
воображаемой проблемой создали вполне реальную проблему: Ваше приложение
может упасть по внешним причинам.
Кстати, обратите внимание, что:
1) close не того файла все равно не пройдет незамеченным — попытка
поработать с закрытым файлом вернет ошибку
2) в Вашем случае assert сработает слишком поздно, и из него трудно
будет понять, что произошло
3) как только вместо read'а будет написан write, использование
assert'а сразу станет некорректным, а это совершенно неочевидно. Первый
же индус, который добавит в фаш код запись в файл, не обратит никакого
внимания на assert.
Здравствуйте, adontz, Вы писали:
A>Здравствуйте, Cyberax, Вы писали:
C>>Пусть шлют coredump, по которому можно посмотреть stacktrace.
A>Я рыдаю. Ты хоть раз работал с пользователями? ИМХО за такие выходки PM настучит по голове, а support team добавит.
а как иначе дебужить? Просить логи или эксперементальную версию запускать?
Здравствуйте, pavel_turbin, Вы писали:
_>а как иначе дебужить? Просить логи или эксперементальную версию запускать?
Логи можно запросто и самому слать. Те же log4*** имеют EMailAppender или как он там называется.
Custom Build это уже совсем на крайний случай. Логи кстати не объязательно писать всегда. Может быть инсталляция программы и отдельно мини-инсталляция, которая включает запись и отсылку логов.
Пользователю так гораздо проще. В особенности если ошибка нестабильная и не известно когда произойдёт.
Я конечно понимаю, что dump это очень круто и супер-полезно, но какой процент пользователей, пусть даже под linux, сумеет его правильно записать и отослать? Хорошо подумай, прежде чем назовёшь цифру больше 10.
adontz wrote: > C>Пусть шлют coredump, по которому можно посмотреть stacktrace. > Я рыдаю. Ты хоть раз работал с пользователями? ИМХО за такие выходки PM > настучит по голове, а support team добавит.
Делайте автоматический присылатель core-ов. У нас так и сделано для
Windows (под Линукс у нас серверный софт, который обслуживают админы).
Здравствуйте, Cyberax, Вы писали:
C>Делайте автоматический присылатель core-ов. У нас так и сделано для Windows (под Линукс у нас серверный софт, который обслуживают админы).
Это замечательно конечно, примечик такой штуки даже на CodeProject есть, но по сути неприятная выходит ситуация. Была ошибка после которой можно было восстановится, а вместо этого программа валится, теряются данные и т.д. и т.п.
adontz wrote: > > C>Делайте автоматический присылатель core-ов. У нас так и сделано для > Windows (под Линукс у нас серверный софт, который обслуживают админы). > > Это замечательно конечно, примечик такой штуки даже на CodeProject есть, > но по сути неприятная выходит ситуация. Была ошибка после которой можно > было восстановится, а вместо этого программа валится, теряются данные и
Если при аварийном завершении программы теряются данные, то это ошибка,
и ее надо устранить.
Аварийное завершение может произойти и без всякой вины программы.
Например, из-за сбоя в электропитании. Программа должна предусматривать
безопасность пользовательских данных при такой ситуации.
Есть список, а точнее — таблица дескрипторов. exit() только говорит ядру о том, что процесс завершился, а освобождением ресурсов занимается само ядро. В том числе и закрытием дескрипторов. fopen() & Co для работы с файлами в итоге делают системные вызовы, и хранить в библиотеке отдельный список указателей на структуру FILE не вижу смысла.
A>Всё равно, поиск в списке из нескольких десятков элементов это мелочи. Ввод-вывод крайне редко является узким местом. А если является, то меняют аппаратуру, а не переписывают программу.
Правильно. Тормозит программа — купите процессор побыстее, поставьте памяти побольше. Переразведите плату под более быстрый микроконтроллер
ДД>>Бывает. Машины ненадежны, но люди еще ненадежнее. Но это не повод обвинять в кривости библиотеку, которая работает в соответствии со стандартом.
A>А где я обвиял в кривости? Ты ни с кем меня не перепутал?
Ты — нет, обвинял Кирпа В.А — автор первого сообщения. А ты, насколько я понял, с ним согласен. Если не так — извини.
ДД>>Тогда может ты предложишь проверять на валидность указатели в realloc, free, pthread_create, sem_post и т.д.?
A>А почему нет?
Хотя бы потому что в стандартной библиотеке это не нужно.
A>Идеология не позволяет?
В какой-то мере — да.
ДД>>Для быстрой и дешевой разработки ПО, некритичного к кривости рук программиста, существуют соответствующие технологии и языки.
A>Кривизна рук тут ни при чём. Ошибки делают все.
Да. Но некоторые их исправляют, а некоторые о них даже не подозревают.
A>Я не очень понимаю, зачем надо гордится тем, что "язык на котором я программирую позволяет совершать более изощерённые ошибки" и тем более лелеять это как святыню.
Не совсем понял, к чему это, ну да ладно.
Обязательно бахнем! И не раз. Весь мир в труху! Но потом. (ДМБ)
Здравствуйте, Tanker, Вы писали:
_>>а вы думаете под Windows API функции не используют HeapAlloc? вы ошибаетесь. Однако, если память не выделена, CreateFile обломится.
T>Все правильно, только дескриптор закрывай сколько хочешь, худа от этого не будет. Тебе вернется код ошибки и все.
А кто сказал, что в glibc нельзя закрывать дескриптор сколько угодно? Вернется код ошибки и все.
Обязательно бахнем! И не раз. Весь мир в труху! Но потом. (ДМБ)
Здравствуйте, adontz, Вы писали:
C>>Пусть шлют coredump, по которому можно посмотреть stacktrace.
A>Я рыдаю. Ты хоть раз работал с пользователями? ИМХО за такие выходки PM настучит по голове, а support team добавит.
-1
Я позволю Вам напомнить, что в XP автоматом включили создание дампов и отсылку их разработчикам, создание дампов в ОС Виндовз появилось намного раньше, но даже MS нашла рациональное зернго в дампах.
Здравствуйте, Tanker, Вы писали:
T>Здравствуйте, MaximE, Вы писали:
>>> Раз они юзают malloc, free то пусть будут добры не попадать в условия когда >>> портится heap (например повторное закрытие файла)
ME>>Лучше пусть они маскируют ошибки в твоем коде, так?
T>Маскируют ? Если бы во время повторного закрытия валился аналог Debug Break, это было бы неплохо, а так валится хип. Увидел программист, что хип повалился, что ему дальше делать ?
Для того, чтобы увидить чьло хип повалился, достаточно использовать valgrind.
ИМХО, вся проблема людей когда-либо работающих с MS OS в том, что они излищне доверчивы к ПО, и считают, что ПО все должно делать за них.
НО, даже в MSVC 2003 при создании консольного приложения — отладочная куча сама по себе не подрубается, это надо делать ручками. Так что притензия не принимается
Здравствуйте, srggal, Вы писали:
S>Я позволю Вам напомнить, что в XP автоматом включили создание дампов и отсылку их разработчикам, создание дампов в ОС Виндовз появилось намного раньше, но даже MS нашла рациональное зернго в дампах.
Неправильно написал. правильно так.
Я позволю Вам напомнить, что в XP автоматом включили создание дампов и отсылку их разработчикам ОС, создание дампов в Виндовз появилось намного раньше, но даже MS нашла рациональное зернго в дампах.
Кроеме того я не сказал, что дампы плохо. Я сказал что плохо — падающее приложение и лучше до этого не доводить.
Здравствуйте, Pzz, Вы писали:
Pzz>Если при аварийном завершении программы теряются данные, то это ошибка, и ее надо устранить.
Это в теории. На практике я знаю только два пакета програм MS Office и Corel которые так делают. Причём в пакете Corel это не работает Все остальные теряют данные.
adontz wrote: > Это в теории. На практике я знаю только два пакета програм MS Office и > Corel которые так делают. Причём в пакете Corel это не работает Все > остальные теряют данные.
Пять копеек от линуксоида — ViM. При большинстве вариантов настройки
(включая умолчания) он скидывает действия (иногда их результаты) на
диск. Причём это делается так же, как и swap, когда памяти мало.
Вероятность успешного восстановления стремится к 1. Впрочем, под Windows
всё у него так же.
Ну и, кстати, когда я роняю Opera или Firefox (с SaveSession), список
адресов, которые я держал открытыми, не теряется. Что, впрочем, иногда
приводит к необходимости с этим бороться, но в среднем очень удобно.
Здравствуйте, Tanker, Вы писали:
ME>>Лучше пусть они маскируют ошибки в твоем коде, так?
T>Маскируют ? Если бы во время повторного закрытия валился аналог Debug Break, это было бы неплохо, а так валится хип. Увидел программист, что хип повалился, что ему дальше делать ?
Какой такой программист? У меня компы в стойке, за ними нет операторов.
A>А подумать, прежде чем писать можно было? Ей передаётся не абы какой указатель, а выделенный fopen. Что мешает хранить где-то внутри список всех указателей выделенных fopen и при вызове fread, fwrite, fclose проверять валидность переданного указателя простым его вхождением в список? Ничего не мешает, кроме лени и желания гнать понты. По сравнению со скоростью ввода-вывода это копейки. Те же дескрипторы в Windows это сплошь указатели или индексы в таблицах, однако использование левого дескриптора не приводит ни к какому краху. UB на сегодня это плохой тон или детский сад, уж сам выбери.
adontz wrote: > > Pzz>Если при аварийном завершении программы теряются данные, то это > ошибка, и ее надо устранить. > > Это в теории. На практике я знаю только два пакета програм MS Office и > Corel которые так делают. Причём в пакете Corel это не работает Все > остальные теряют данные.
Вы точно знаете? Вы попробовали _все_ остальные программы? Сколько Вам
лет, простите?...
Здравствуйте, Pzz, Вы писали:
Pzz>Вы точно знаете? Вы попробовали _все_ остальные программы? Сколько Вам лет, простите?...
Я сказал я знаю два пакета,я не сказал, что я знаю, что етсь только два пакета. ВСе остальные программы никто не пробовал. Но пока что программ намечается от силы 5, если считать и браузеры. Можете расширить этот список вне зависимости от возраста.
Здравствуйте, Кирпа В.А., Вы писали:
КВА>Здравствуйте, ДимДимыч, Вы писали:
ДД>>Здравствуйте, adontz, Вы писали:
КВА>активность на этом форуме за счет моего топика значительно подросла КВА>только вот за такой интересный топик минусы получать не очень приятно
ИМХО В вашем топике нет АБСОЛЮТНО ничего интересного, активность подросла за счет подтянувшихся апологетов WINDOWS, с соседнего WINAPI и философов из ФИЛОСОФИИ.
Если так и дальше будет, то или начнут модерировать модераторы, или появится новый форус — ТОЛЬКО О ЮНИКС и ТОЛЬКО ДЛЯ ЮНИКСЛОИДОВ
Здравствуйте, Kemm, Вы писали:
K>Здравствуйте, adontz, Вы писали:
ME>>>memory footprint, мобильные ус-ва приходят тут же на ум. Просто вот так (шелчок пальцами) все приложения, которые используют FILE* будут больше кушать памяти? A>>Реализация несколих списков да и сами списки вряд ли займут сущесвенное количество памяти. Если ты отроешь 250 файлов и будешь хранить валидные указатели в виде RB дерева (чтобы быстрее искать), то на 32битной платформе получишь (3 указателя + 1 указатель) * sizeof(void *) * 250 = 4000 байт данных. ИМХО даже для мобильных устройств это совершенно смешной объём
K>Расскажите об этом разработчикам встроенных систем всякого рода. Вы их осчастливите запасом хорошего настроения на день. От хохота.
Как как раз тот разработчик встроенных систем, отправлю обоих пить пиво в сторонке и нас не трогать, потому как Линуха у меня не будет и Винды тем более, потому что не поместится да и не нужен мне он. и вообще у самого крутого проца из серии 32К флеш памяти, и около 16К Рам, ну с господа куда вы собираетесь свои дескрипторы засовывать .
Здравствуйте, Kemm, Вы писали:
K>Здравствуйте, Stoune, Вы писали:
S>>Как как раз тот разработчик встроенных систем, отправлю обоих пить пиво в сторонке и нас не трогать, потому как Линуха у меня не будет и Винды тем более, потому что не поместится да и не нужен мне он. и вообще у самого крутого проца из серии 32К флеш памяти, и около 16К Рам, ну с господа куда вы собираетесь свои дескрипторы засовывать .
K>Встроенные системы тоже разные бывают...
Только вот таких как моя, или даже с ешё большими апаратными ограничениями в количественном выражении будет наверное на порядок больше чем всех остальных вместе взятых(часы, кофемолки, кросовки и очень много всего). Ну и на чьей стороне сила, брат?
Здравствуйте, Кирпа В.А., Вы писали:
КВА>А возмутило меня другое Анализ лога valgrind показал что библиотечные КВА>функции fprintf, fclose вовсю юзают malloc, free
Каким боком функции glibc относятся к Linux ?
Что, других рантаймов нет ?