LINUX.ORG.RU
ФорумTalks

Почему вся документация написана так всрато?

 , , ,


0

2

Сначала хотел пожаловаться на конкретную систему, но копнули глубже и выяснилось, что это общая проблема.

Windows

Вот берем, например, хвалёный MSDN (до линуксов тоже доберемся).
Рассмотрим функцию _write. Опустим чёртов момент, что они депрекейтнули write в пользу _write с тем же синтаксисом, опустим что под виндой есть суперкосяк с текстовым режимом. Опустим, что может быть установлен parameters_handle, который коллбекнется при передаче невалидных параметров. Опустим то, что сигнатура использует int и unsigned вместо ssize_t и size_t:

int _write(
   int fd,
   const void *buffer,
   unsigned int count
);

Нас интересует такой момент:

If execution is allowed to continue, the function returns -1 and errno is set to one of three values: EBADF, which means the file descriptor is invalid or the file isn't opened for writing; ENOSPC, which means there isn't enough space left on the device for the operation; or EINVAL, which means that buffer was a null pointer, or that an odd count of bytes was passed in Unicode mode.

Итого нам говорят, что:

  • Если передан невалидный fd - продолжать нельзя
  • Если на диске закончилось не хватает место - то продолжать нельзя
  • Если передан кривой буфер - то продолжать нельзя

Ну то есть функция возвращает ошибку всего в трех случаях и все они критические. Окей, а что насчет возврата числа меньше, чем передано в count? Когда такое может быть? В теории когда выполнение функции прервано сигналом или когда записалось N байт и кончилось место. Однако под windows сигналы обрабатываются специально установленным коллбеком и такой вариант отметается. А что касается диска, то:

If the actual space remaining on the disk is less than the size of the buffer the function is trying to write to the disk, _write fails and doesn't flush any of the buffer's contents to the disk

То есть она не попытается записать то, что возможно (что неимоверно тупо, поскольку между моментом проверки места и попыткой записи это самое место могло появиться). Ну то есть _write под windows никогда не вернет значение меньше count (и даже больше count не вернет, несмотря на то что в текстовом режиме запишется больше(!) байтов). Еще есть прикол с 0x17 байтом.

По итогу - нигде в документации не записано - а вернет ли когда-либо _write что-то кроме -1 или count. Если никогда не вернёт, то смысла в возвращаемом count нет. Поведение сломано, сигнатура сломана, доломайте уже контракт. Причем (якобы) существует функция write, но она объявлена устаревшей и плохой, негодной функцией.

The name is deprecated because it doesn’t follow the Standard C rules for implementation-specific names.

Linux

С чего, собственно, всё началось. Читали в качестве групповой терапии ман man 2 write. И нашли такое:

       The number of bytes written may be less than  count  if,  for  example,
       there  is  insufficient space on the underlying physical medium
       Note  that  a  successful  write() may transfer fewer than count bytes.
       Such partial writes can occur for various reasons; for example, because
       there was insufficient space on the disk device to write all of the re‐
       quested bytes

Но в конце в списке errno видим:

       ENOSPC The device containing the file referred to by fd has no room for
              the data.

Т.е. сначала нам два раза говорят, что если на диске не хватает места то запишет сколько влезет и вернет N, а в списке ошибок нам говорят, что будет выставлено -1 и установлен ENOSPC как errno.

Разгадка тут простая - если на диске есть хотя бы один байт свободного пространства - оно запишет один байт. Если там ноль - то вернет -1 + ENOSPC. Но где конкретно это написано? Почему документация превратилась в противоречащий сам себе кусок текста без этого уточнения? Поведение, кстати, полностью противоположное тому, что задано для windows.

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

И хорошо, если хоть код не лень.

Код тоже лень, но надо)

goingUp ★★★★★
()

Читали в качестве групповой терапии ман man 2 write.

Эээ?

goingUp ★★★★★
()

Противоречия нет. Если insufficient space (недостаточно места), то partial writes can occur, а если no room (совсем нет места), то будет ENOSPC. Разницу межу «недостаточно» и «нет» надо объяснять не в манах, а в учебниках по языку или, возможно, логике.

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

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

// Видос ещё не смотрел, но наверное это как-то связано https://www.youtube.com/watch?v=czzAVuVz7u4

Bad_ptr ★★★★★
()

Вот берем, например, хвалёный MSDN (до линуксов тоже доберемся).
Рассмотрим функцию _write.
Окей, а что насчет возврата числа меньше, чем передано в count?
По итогу - нигде в документации не записано - а вернет ли когда-либо _write что-то кроме -1 или count.

https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/write

Return value

If successful, _write returns the number of bytes written. If the actual space remaining on the disk is less than the size of the buffer the function is trying to write to the disk, _write fails and doesn’t flush any of the buffer’s contents to the disk.

Тебе словарик по англюсику подарить?

LamerOk ★★★★★
()

выяснилось, что это общая проблема.

Попробуй сам написать краткую непротиворечивую документацию к буферу «стакану, который может быть наполовину полон, или наполовину пуст» :)

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

Разницу межу «недостаточно» и «нет» надо объяснять не в манах

Это как «денег нет» и «денег нет совсем» :)

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

Дядя, ну ты хоть перечти, что написал. Я тебе «возможно ли событие, что будет меньше count?» а ты мне «в одном конкретном случае будет count или -1»

PPP328 ★★★★★
() автор топика

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

ну т.е. файловый дескриптор конечно может быть файлом на диске (иногда)

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

а ты мне «в одном конкретном случае будет count или -1»

Ты не понял текста документации. Перечитывай пока не поймёшь. Да, надо приложить усилие, если не знаком с языком.

LamerOk ★★★★★
()

Итого нам говорят, что:

Если передан невалидный fd - продолжать нельзя

If execution is allowed to continue,

Видимо, тут говорится о случаях, когда write возвращается немедленно, без блокировки

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

когда write возвращается немедленно, без блокировки

Не, allowed to continue это потому что в предыдущем предложении (которое я не процитировал) говорится про установку коллбека для сигнализации о некорректных параметрах и там можно настроить так что вывалится гуёвая ошибка и если там нажать retry/continue то приложение продолжится

PPP328 ★★★★★
() автор топика

Т.е. сначала нам два раза говорят, что если на диске не хватает места то запишет сколько влезет и вернет N, а в списке ошибок нам говорят, что будет выставлено -1 и установлен ENOSPC как errno.
no room for the data.

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

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

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

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

If successful, _write returns the number of bytes written.

Приведите пример, когда вернется значение меньше count.

Когда number_of_bytes_written < count.

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

есть отдельные пространства дескрипторов, хэндлов и сокетов

Да, там всё сделано по уму, вместо юниксовых грязных хаков в духе «херак-херак».

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

Приведите пример, когда вернется значение меньше count.

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

goingUp ★★★★★
()

Почему документация превратилась в противоречащий сам себе кусок текста без этого уточнения?

Объяснение довольно простое, в крупных проектах люди пишущие код и люди пишущие документацию к нему - это разные люди.

Obezyan
()

Потому что ее пишут по стандартам. А в вашем примере, кстати, нет противоречий. Есть ваши неоправданные ожидания, вызванные незнанием или непониманием стандартов, по которым данную документацию писали.

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

Нет. Этот случай там описан и в таком случае не запишется вообще ничего и вернется -1

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

в итоге во всём мире close, а в winsock closesocket. Очень сильно мешает в кроссплатформенном коде, как и остальные отличия winsock

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

Потому что ее пишут по стандартам.

В винде если 0 < свободноеместо < count то вернётся -1
В линуксе если 0 < свободноеместо < count то вернется свободноеместо

Напомните, по какому стандарту так?

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

Не запишется. Там прямо указано, что операция откатится потому что буфер записи очистится и не будет флюшиться.

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

буфер записи очистится и не будет флюшиться.

Ладно, давай еще раз. Мы вызываем write. Буфер большой, место есть, буфер начинает физически сбрасываться на диск. Параллельно с нами пишет другой процесс, и где-то на средине заканчивается место.

goingUp ★★★★★
()
int _write(
   int fd,
   const void *buffer,
   unsigned int count
);

Нет в ядре Windows такой функции.

EBADF
ENOSPC
EINVAL

И это не системные коды ошибок.

Так что претензии должны быть не к Windows, а к авторам либы (индусам на аутсорсе у майкрософта).

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

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

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

PPP328 ★★★★★
() автор топика

смузихлеб, ничего кроме текстовых файлов за всю жизнь не открывавший?

или вендовоз, мыслящий лишь папками и файлами файловыой системы.

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

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

n_play
()

Это ты еще на Glib и собственно жертв инцеста GTK\GObject документацию не видел.

windows10 ★★★★★
()

вернет ли когда-либо _write что-то кроме -1 или count.

чем-то напомнило дефолтное поведение SSL_write* из OpenSSL. Ты раскрыл мне глаза, почему они сделали такое по дефолту и требуют приседаний, чтобы включить поведение как у write в линуксе например.

понятно о какой кросс платформенности и поведении они заботились впервую очередь.

Разгадка тут простая - если на диске есть хотя бы один байт свободного пространства - оно запишет один байт.

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

а что еще умеешь? бинарный поиск наверно можешь написать с закрытыми глазами и с первого раза?

вы нам подходите!

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

эта «либа» - часть windows

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

MSVCRT – это скорее часть SDK, которую положили в комплект чтобы упростить юзеру жизнь (и этим же иногда усложняя ее многократно).

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

quwy
()

Но где конкретно это написано?

в документации так и написано - write имеет право писать меньше, и это не ошибка. Ошибка это -1 и errno.

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

Потому что погромистам лень писать что-то, кроме кода. И хорошо, если хоть код не лень.

Да, но не все такие. Я свою документацию сам писал и поэтому думали, что я не один. :D
http://лабст.рф/manual/klest-help/klest-help.html.

xwicked ★★☆
()
Последнее исправление: xwicked (всего исправлений: 1)
Ответ на: комментарий от n_play
забавно не задолбленную молитву
а(«в подражание» Фейману с барометром) 
выкатывать разные выверты которые по сути поиск за лог - но с нюансами 
например - тернарный выбор : 
https://stackoverflow.com/questions/249392/binary-search-in-array/68322246#68...
бинарный поиск :(
либо поиск сжигая биты в дельте краёв(там и Кнут не скажет какая Oо :) :
т.е l за ноль r - дельта между реальными границами 
тогда императивным циклом идём от старшего бита к млатшего и тестируеем значение - т.е тот же выбор но с мещёный :)

ТСу: код когерентен доке когда есть обостароннее транслирование но тогда и баги будут документированны как фичи

и баги проектирования фичизированы в код

дока не может быть тождественна коду - это постулат индустрии

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

Ну то есть виндовая функция не соответствует стандарту сразу во многих местах, начиная с size_t и заканчивая тем, что она должна записать сколько поместилось а не «или всё или ничего».

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

В виндовой - не написано. Этот момент проигнорирован, что и вызывает вопросы.

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

Ты не отличаешь методики изложения от содержания или не понимаешь, почему 2 функции с одинаковым названием работают по-разному?

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

почему 2 функции с одинаковым названием работают по-разному

Microsoft объявляет, что они posix-compilant
Функции работают по-разному чем posix.

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

Microsoft объявляет, что они posix-compilant

Какая конкретно функция и где объявлена posix-compilant?

aiqu6Ait ★★★★
()

Чтобы написать хорошую документацию нужен хороший специалист, умеющий писать связный текст. Таких еще называют «технический писатель». Причем это должен быть не просто чел, который умеет в текст, а еще и инженер, который понимает, о чем он пишет. Вот только тогда дока будет нормальная. Но зачастую доку пишут инженеры, а у них свое видение того, «как надо», что ожидаемо на выходе будет понятно только им или инженерам такого же уровня. И они часто вообще не умеют писать связный текст. А еще много где даже не знают, что бывают техписы, а если и знают, то забивают болт на найм таких специалистов.

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

Дык, ты-то сверхчеловек, а я про обычных жалких смертных говорю.

apt_install_lrzsz ★★★
()
Закрыто добавление комментариев для недавно зарегистрированных пользователей (со score < 50)