Нашли или выдавили из себя код, который нельзя назвать нормальным,
на который без улыбки не взглянешь?
Не торопитесь его удалять или рефакторить, — запостите его на
говнокод.ру, посмеёмся вместе!
fstream:=tstreamex.Create(signaturepath,fmShareDenyWrite);
FLock.Enter;
try
while not fstream.EOS do
begin
obj:=tsignature.create;
try
obj.AddingDate:=fstream.ReadDate;
obj.Comment:=fstream.ReadString;
fstream.ReadBuffer(Len, SizeOf(Len));
obj.MStream.SetSize(len);
fstream.ReadBuffer(obj.mstream.memory^, len);
fsignlist.Add(obj);
except
obj.Free;
raise esignatureloadingerror.Create('Signature read error');
end;
Стрим читает из файла сохраненный объект. К сожалению, подобный подход используется даже в серьезных коммерческих проеках, это классика.
Если что-то поменять в файле хоть на 1 байт, стрим промахнётся мимо поля - прога либо съест всю доступную системную память либо обрушится с Access Violation.
В любом случае, память будет испорчена, и дальнейшее выполнение программы чревато UB.
Кстати, а не грозит ли юзание структур порчей памяти? Допустим, хотим определить валидность заголовка, загружаем структуру, а в файле - трешак.
Не будет ли обращения по ложному адресу? UB?
Сюка ты меня заебал.
Увижу при встрече, сыпану в глаза тебе горчичный порошок. Пока ты корчишься от боли, я привяжу тебя чтоб не дергался. Досыплю порошка в глаза и перемешаю в глазницах. Возьму связку сосисок и выебу тебя, как анальными бусами. Дальше взглотнешь 2 литра колы и насильно засуну в тебя ментос, чтоб твое ебало посинело. Пока ты синеешь и кричишь (От удовольствия или боли?), вспорю пузо и толстую кишку и вытощу ту связку сосисок с говном, намажу тем самой глазной горчицей и засуну в тебя. Возможно тебя вырвет, но советую этого не делать.
> писать на дельфях в 2016м это самая что ни на есть анскилябрщина
Настоящая анскилябрщина - считать что год написания имеет какое-то отношение к анскилябрщине.
Ну как сказать... Для своего времени делфа вполне годная была. Назови мне ещё один иструмент со времён делфи, где можно было формошлёпствовать и ставить компоненты без ёбли.
А ещё там отладчик высокого качества. От делфи, когда садишься за нее работать, веет теплотой и дружелюбием, чего не скажешь о приблудах от майкрософта. ненавижу.
Играет и воет, как зверь молодой,
Завидевший пищу из клетки железной;
И бьется о берег в вражде бесполезной
И лижет утесы голодной волной... Вотще! нет ни пищи ему, ни отрады:
Теснят его грозно немые громады.
Я нихуя не понял, но в нормальных языках копировать содержимое файла/сокета в плоскую структуру (без указателей) - это безопасно, хоть и непортируемый говнокод.
> Кстати, а не грозит ли юзание структур порчей памяти? Допустим, хотим определить валидность заголовка, загружаем структуру, а в файле - трешак.
Не будет ли обращения по ложному адресу? UB?
Э, да ты совсем нуб что ли. Если размер файла меньше размера структуры то прочитать не удастся, будет исключение. А если больше - все поля прочитаются. Ну да, в полях может быть мусор, на то он и заголовок что надо будет сигнатуры сравнить, но откуда там ложные адреса и UB?
>> Если размер файла меньше размера структуры то прочитать не удастся, будет исключение. А если больше - все поля прочитаются. Ну да, в полях может быть мусор
Если вылетело исключение - разве сие не знак того, что испорчена память? Вдруг код затёр служебные заголовки? Мусор в полях - тоже UB, как мне кажется.
> Мусор в полях - тоже UB, как мне кажется.
Ну тогда при объявлении любой локальной переменной происходит UB. Это уже потом мы присваиваем ей значение, а до этой строчки с присвоением - полнейшее UB.
>>тебе ось в адресное пространство не замапает просто так.
Кстати!! Расскажи мне как работает MMIO и DMA при наличии MMU?
Драйвер как-то умно читает таблицы странц и вычисляет настоящий адрес?
> Драйвер как-то умно читает таблицы странц
Да там у ядер специальные апишки для трансляции адресов есть, чтобы драйверы не заморачивались. Типа "выдели мне непрерывный кусок физической памяти чтобы до него могла дотянуться вот эта железка и дай адрес, который можно ей скормить" или "замапай мне mmio адреса вот этой железки". И дальше там ядро настраивает все кеши, смещения на мостах, IOMMU если есть и т.п.
Это про DMA, как я понял?
Типа драйвер просит у ядра буфер, и скармиливает его адрес DMAшке на борту карты, и карта туда пишет-пишет и потом делает interrupt?
а MMIO как?
Ну вот сидит карта на шине и слушает адреса с FOO по BAR.
Если я сделаю mov [FOO], 42 то FOO через MMU преврарится в черте-чо. Как же драйвер умеет записать ИМЕННО в FOO?
Ты говоришь ядру "замапай куда-нибудь mmio range вот этой вот железки". Оно тебе даёт виртуальный адрес (назовём его mapped). А таблицу трансляции для MMU для этого адреса оно тебе так настроит, что когда ты полезешь по адресу mapped + 8, то адрес уйдёт на шину правильно и, с учётом всех мостов в сторону железки, которые могут его немного подвинуть, прилетит к ней как 8 (или как base + 8, не знаю точно, где последняя трансляция идёт - в самой железке или в ближайшем к ней мосту)...
иными словами процессор ВСЕГДА обращение к памяти прогоняет через MMU, но ядро настраивает таблицы так, что MMU мапит такие обращения не абы-куда а в нужное место.
ужасная жесть этот ваш протектед мод
то-ли дело дос:
Вполне себе многозадачненько! Причем если запрограммировать таймеры (там же их было два вроде) то чем не многозадачность?;)
Причем не было гонок, не нужно было делать fence потому что DOS не умел более одного CPU (да?).
у iOS это связано с желанием не тратить батарейку на всяких пидарасов. Технически Darwin @ XNU вполне себе многозадачна, как ты понимаешь:)
Кстати говоря даже сейчас чтобы что-то делать в офне нужно это явно попросить (через plist) и список дел крайне ограничен) Тебя либо "иногда будут будить", либо разрешат быть всегда в фоне если ты плеер или навигатор.
Ну то-есть нельзя невозбранно простые числа искать за счет пользователя в фоне. А в ондроиде можно)
> сервис-то можно сделать
Один хуй засыпает... Без wake lock у меня не получалось нормально дёргать странички с ГК. Сервис просыпался только с какими-нибудь гугловскими прогами или когда экран включал... Алармы тоже не особо помогают без лока, чуть управление вернёшь - сразу в сон.
Ну если структура состоит только из примитивов и в ней нет указателей - ничего страшного не случится. Ситуация ровно такая же, как если тебе в консольке или gui передадут мусор вместо данных.
Написание "нормального" сериализатора/десиализатора — задача сама по себе нетривиальная, особенно, если нужно энкодить указатели.
Какую именно проблему решаем-то?
Если хочется не читать гигабайты при случайных повреждениях — добавляем чексуммы + проверяем, что размеры буферов адекватные.
Когда я пилил специализированную штуку для хранения на диске, я вообще ничего в память не копировал: хранил файлы так, чтобы их можно было mmap-ить в память + использовал чексуммы для проверки записей.
Правда, была завязка на 64-разрядные системы — файлы были большие.
Ну ты сорвал покровы. Когда читаешь файл read'ом, страницы все равно сначала копируются в кэш, а потом еще раз копируются в пользовательский буфер. Так что при мапинге файла меньше копирований и потенциально меньше переходов в ядро. Так-то, в яндексе веников не вяжут, это пирфоманс.
Это ещё до яндекса было, но в яндексе тоже любят mmap.
Не столько из-за выигрыша пирфоманса на копировании (который не такой уж и большой, кстати), сколько из возможности быстро начать обрабатывать запросы, не дожидаясь, пока распарсится в память здоровенный индекс.
> страницы все равно сначала копируются в кэш, а потом еще раз копируются в пользовательский буфер.
Я даже больше тебе скажу. При передачи из ядра в память приложения - они копируются ещё раз. С винта читается в буфер через DMA, а он может работать только с данными выравненными на границу параграфа. Да и не гоже читать в чужую память, ибо глядишь пока драйвер "дмашкой" будет выжидать раскручивания цилиндров винта и затем хреначить в буфер юзера - процесс за это время успеет повалится. Так что сначала хуярят в страницу в кернелспейсе, а потом в страницу юзерспейса уже перекопирывают. А там ещё всякие промежуточные менеджеры есть в оси в стеке драйверов, которым нужно поснифать твои буфера для каспера например или что-то ещё сделать, так что и там все копируется в очередной раз. Так что не так страшно будет пару копирований или десятка. С винта все равно на много порядков медленне поднимается. Ну а так да, если мапиш память - там групка страниц сразу переписывается с винта, а потом без копирований эта групка страниц просто ремапится изкернелспейса драйвера в юзерспейс. В целом ммапингчтение обычно медленне обычного чтения, так как префетча обычно нет или он работает адекватно только под некоторые применения в приложениях.
> При передачи из ядра в память приложения - они копируются ещё раз.
Шта? Я и сказал, что сначала кусок файла вычитывается в страницу пейджкеша, а потом копируется в юзерспейс. Где там "еще раз"?
Кешер винта отдельно (часть ос), драйвер винта с в кернелспейсе - отдельно, приложение в юзерспейсе - отдельно. Приложению страницы из кешера отдавать не станут напрямую, как и кешеру из драйвера винта тоже не станут. Так что везде копирование. Их там больше чем ты думаешь. Кешер обычно частично в кернеле, частично в юзерспейсе работает, но это от версии оси и её назначения сильно зависит.
А так нагрузка на системный своп сильно снижается с юзаньем мапинга, тк по сути замапленный файл становится свопфайлом и можно любую давно не юзанную страницу выгрузить, а вот если ты себе закопировал обычным ридом в буфер приложухи в хип - тут этот буфер только в основной системный своп отправлять, которого может и не хватить
Я не втыкаю, что ты говоришь тут. Кусок файла вычитывается в пейджкэш. Дальше если read, то из пейджкэша копируется в пользовательский буфер, если mmap, то страница мапится в память процесса без копирований. С чем ты споришь-то, ты можешь пояснить конкретно?
Во-первых, ты не знаешь, что я думаю, во-вторых, ты кроме тех, что назвал я, ты назвал только копирование из драйвера в пейджкэш. В-третьих, если приложение не только файоы с диска читает, но майнит биточки, то такты цпу лишними не будут. Че ты тут умничаешь? Не знаешь, не лезь.
> В-третьих, если приложение не только файоы с диска читает, но майнит биточки, то такты цпу лишними не будут
У обычного рида тоже плюсы свои есть. У него больше троугхпут и лучше работа кешера с точки зрения кешмисов, чем у ммапа, так что ещё бабушка на двое сказала, что лучше для конкретной ситуации. Не чего думать категорями царских оптимизаций экономий на спичках
Блядь, как у вас всё сложно. Нет, лучше писать на "PHP" с использованием "DevelNext"-а - он сам прекрасно управится с памятью, кэшем и прочей поеботой...
Еще мне кажется, роман кашiцiн говорил о том, что ему не нужно строить в памяти структуру на основе данных из файла, а не о том, что не надо данные загружать.
Виват, Кашицын.
>>Если хочется не читать гигабайты при случайных повреждениях — добавляем чексуммы + проверяем, что размеры буферов адекватные.
У меня так сделано, но почему-то это показалось мне хаком. Оказывается, не ламерство.
BagorCtretora,
huesto,
guestinho,
CrashTesterAnusov,
bagor,
barop
- попадают в список свитка-минусатора. Вы для меня больше не существуете. Прощайте.
Ты когда осилишь автоматизировать свой безблагодатный труд? Неужели не раздражает делать одно и тоже однообразное действие? Тогда какой-же ты программист, если не можешь автоматизировать простые действия?
Я её как минимум разноображу интересными языками и алгоритмами. А вот когда ты осилишь хоть что-то из автоматизации? Я из тех, кто ненавидит повторяющиеся действия, которые мне надо делать самостоятельно. Поэтому я их или автоматизирую, или не делаю совсем.
> Я из тех, кто ненавидит повторяющиеся действия, которые мне надо делать самостоятельно.
Надеюсь, в виме сидишь, не правишь в ide повторяющиеся строки руками?
В гитхаб атоме есть мощные средства для редактирования копипаста: поиск и замена по всему проекту регулярками, множественные курсоры позволяющие редактировать сразу несколько одинаковых участков кода.
Увижу при встрече, сыпану в глаза тебе горчичный порошок. Пока ты корчишься от боли, я привяжу тебя чтоб не дергался. Досыплю порошка в глаза и перемешаю в глазницах. Возьму связку сосисок и выебу тебя, как анальными бусами. Дальше взглотнешь 2 литра колы и насильно засуну в тебя ментос, чтоб твое ебало посинело. Пока ты синеешь и кричишь (От удовольствия или боли?), вспорю пузо и толстую кишку и вытощу ту связку сосисок с говном, намажу тем самой глазной горчицей и засуну в тебя. Возможно тебя вырвет, но советую этого не делать.
Этот смайл ступорит меня.
писать на дельфях в 2016м это самая что ни на есть анскилябрщина
Настоящая анскилябрщина - считать что год написания имеет какое-то отношение к анскилябрщине.
Играет и воет, как зверь молодой,
Завидевший пищу из клетки железной;
И бьется о берег в вражде бесполезной
И лижет утесы голодной волной...
Вотще! нет ни пищи ему, ни отрады:
Теснят его грозно немые громады.
Вы словно голуби: только "курлы-мурлы", а пользы - 0. Только белье на веревке пачкаете.
http://govnokod.ru/20875
Не будет ли обращения по ложному адресу? UB?
Э, да ты совсем нуб что ли. Если размер файла меньше размера структуры то прочитать не удастся, будет исключение. А если больше - все поля прочитаются. Ну да, в полях может быть мусор, на то он и заголовок что надо будет сигнатуры сравнить, но откуда там ложные адреса и UB?
Если вылетело исключение - разве сие не знак того, что испорчена память? Вдруг код затёр служебные заголовки? Мусор в полях - тоже UB, как мне кажется.
Ну тогда при объявлении любой локальной переменной происходит UB. Это уже потом мы присваиваем ей значение, а до этой строчки с присвоением - полнейшее UB.
Поэтому и советуют инициализировать переменную сразу в объявлении.
Ну типа
char *foo;
*(foo) = 1; //превратились в кирпич или сожгли оборудование
Ну MMIO тебе ось в адресное пространство не замапает просто так. А вот если без оси...
Кстати!! Расскажи мне как работает MMIO и DMA при наличии MMU?
Драйвер как-то умно читает таблицы странц и вычисляет настоящий адрес?
Да там у ядер специальные апишки для трансляции адресов есть, чтобы драйверы не заморачивались. Типа "выдели мне непрерывный кусок физической памяти чтобы до него могла дотянуться вот эта железка и дай адрес, который можно ей скормить" или "замапай мне mmio адреса вот этой железки". И дальше там ядро настраивает все кеши, смещения на мостах, IOMMU если есть и т.п.
Типа драйвер просит у ядра буфер, и скармиливает его адрес DMAшке на борту карты, и карта туда пишет-пишет и потом делает interrupt?
а MMIO как?
Ну вот сидит карта на шине и слушает адреса с FOO по BAR.
Если я сделаю mov [FOO], 42 то FOO через MMU преврарится в черте-чо. Как же драйвер умеет записать ИМЕННО в FOO?
вот я в глаза долблюсь
теперь понятно
типа я говорю едру "пиши по адресу 0x1234", а оно само через таблицы высчитывает реальный адрес
да?
иными словами процессор ВСЕГДА обращение к памяти прогоняет через MMU, но ядро настраивает таблицы так, что MMU мапит такие обращения не абы-куда а в нужное место.
ужасная жесть этот ваш протектед мод
то-ли дело дос:
Так точно.
> ужасная жесть этот ваш протектед мод
Запили свою 64-битную ось с маппингом 1:1 🙂
Программ-то больше чем одна)
Ну сделай почти-однозадачную, как DOS.
З.Ы. Первые iOS'ы вроде тоже как китайские телефоны были - в фоне только плейер да будильник. И ничё, пипл хавал...
Вполне себе многозадачненько! Причем если запрограммировать таймеры (там же их было два вроде) то чем не многозадачность?;)
Причем не было гонок, не нужно было делать fence потому что DOS не умел более одного CPU (да?).
у iOS это связано с желанием не тратить батарейку на всяких пидарасов. Технически Darwin @ XNU вполне себе многозадачна, как ты понимаешь:)
Кстати говоря даже сейчас чтобы что-то делать в офне нужно это явно попросить (через plist) и список дел крайне ограничен) Тебя либо "иногда будут будить", либо разрешат быть всегда в фоне если ты плеер или навигатор.
Ну то-есть нельзя невозбранно простые числа искать за счет пользователя в фоне. А в ондроиде можно)
Если есть право на wake lock. Иначе телефон всё-таки забьёт и уснёт.
но сервис-то можно сделать
Один хуй засыпает... Без wake lock у меня не получалось нормально дёргать странички с ГК. Сервис просыпался только с какими-нибудь гугловскими прогами или когда экран включал... Алармы тоже не особо помогают без лока, чуть управление вернёшь - сразу в сон.
ты можешь поклянчить еще, но не факт что дадут
Так что даже если телефон не спит, то тебя могут выкинуть нахуй (если памяти мало) и фиг ты чего сделаешь
Ну это и на андроиде так. Не дрючить же флешку свопом.
https://developer.android.com/guide/components/services.html
А в ios у тебя такого понятия нет. Ты можешь только попросить будить тебя _иногда_.
Ну либо ты особенный (например, плеер)
https://developer.apple.com/library/content/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/BackgroundExecution/BackgroundExecution.html
Ну и как их проверить? Ведь в любом случае будет утечка памяти.
Написание "нормального" сериализатора/десиализатора — задача сама по себе нетривиальная, особенно, если нужно энкодить указатели.
Какую именно проблему решаем-то?
Если хочется не читать гигабайты при случайных повреждениях — добавляем чексуммы + проверяем, что размеры буферов адекватные.
Когда я пилил специализированную штуку для хранения на диске, я вообще ничего в память не копировал: хранил файлы так, чтобы их можно было mmap-ить в память + использовал чексуммы для проверки записей.
Правда, была завязка на 64-разрядные системы — файлы были большие.
Это ещё до яндекса было, но в яндексе тоже любят mmap.
Не столько из-за выигрыша пирфоманса на копировании (который не такой уж и большой, кстати), сколько из возможности быстро начать обрабатывать запросы, не дожидаясь, пока распарсится в память здоровенный индекс.
Я даже больше тебе скажу. При передачи из ядра в память приложения - они копируются ещё раз. С винта читается в буфер через DMA, а он может работать только с данными выравненными на границу параграфа. Да и не гоже читать в чужую память, ибо глядишь пока драйвер "дмашкой" будет выжидать раскручивания цилиндров винта и затем хреначить в буфер юзера - процесс за это время успеет повалится. Так что сначала хуярят в страницу в кернелспейсе, а потом в страницу юзерспейса уже перекопирывают. А там ещё всякие промежуточные менеджеры есть в оси в стеке драйверов, которым нужно поснифать твои буфера для каспера например или что-то ещё сделать, так что и там все копируется в очередной раз. Так что не так страшно будет пару копирований или десятка. С винта все равно на много порядков медленне поднимается. Ну а так да, если мапиш память - там групка страниц сразу переписывается с винта, а потом без копирований эта групка страниц просто ремапится изкернелспейса драйвера в юзерспейс. В целом ммапингчтение обычно медленне обычного чтения, так как префетча обычно нет или он работает адекватно только под некоторые применения в приложениях.
Шта? Я и сказал, что сначала кусок файла вычитывается в страницу пейджкеша, а потом копируется в юзерспейс. Где там "еще раз"?
А так нагрузка на системный своп сильно снижается с юзаньем мапинга, тк по сути замапленный файл становится свопфайлом и можно любую давно не юзанную страницу выгрузить, а вот если ты себе закопировал обычным ридом в буфер приложухи в хип - тут этот буфер только в основной системный своп отправлять, которого может и не хватить
> Я не втыкаю
А я зато втыкнул защеку, проверь
> Я не втыкаю
Да не страшно.
Я это к тому, что копирований больше чем ты думаешь и это на перформанс не особо то влияет из-за латентности винта
Ты же сам сказал что ты думаешь. Или ты говоришь не то, что думаешь? Или ты говоришь не думая?
У обычного рида тоже плюсы свои есть. У него больше троугхпут и лучше работа кешера с точки зрения кешмисов, чем у ммапа, так что ещё бабушка на двое сказала, что лучше для конкретной ситуации. Не чего думать категорями царских оптимизаций экономий на спичках
Покайся, покайся!..
>>Если хочется не читать гигабайты при случайных повреждениях — добавляем чексуммы + проверяем, что размеры буферов адекватные.
У меня так сделано, но почему-то это показалось мне хаком. Оказывается, не ламерство.
BagorCtretora,
huesto,
guestinho,
CrashTesterAnusov,
bagor,
barop
- попадают в список свитка-минусатора. Вы для меня больше не существуете. Прощайте.
Очень сильно рискуешь, за нами большая армия ботов.
Надеюсь, в виме сидишь, не правишь в ide повторяющиеся строки руками?
ахахахаха
и в нотпаде тоже, ага
чтобы копипаст не стал проблемой