LINUX.ORG.RU

Чем заменить realloc для неизвестного размера принимаемого xml?

 , ,


2

5

Как продолжение топика Помогите нагуглить военный стандарт написания на C .

Есть неизвестного размера (2 - 618 кб (возможно больше)) принимаемый через LAN xml. Возникла необходимость построить суперстабильную систему, для этого пришли к выводу что надо внедрять MISRA-C. А она запрещает realloc. Как быть с принимаемой xml? Буфер статического размера как-то плохо вяжется с неизвестным размером xml. А распарсить xml кусками не представляется возможным.

Отправлять принимаемые байты в файл? А если накрылся диск? На серваке где крутится демон может: закончиться память (стабильно раз в 2-3 дня), посыпаться диск (раз в 2-3 месяца), посыпаться mysql база (раз в 2-3 недели). Серваков 1000+, поэтому вышеперечисленные события случаются каждый день.

Что посоветуете?

★★★★★

... построить суперстабильную систему, для этого пришли к выводу что надо внедрять MISRA-C. А она запрещает realloc.

Знаешь пословицу про дурака, мольбы и лоб? Очень похоже на ваш случай.

Отправлять принимаемые байты в файл?

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

Если всего лишь не хочется использовать realloc, то пишут поток в странички (заранее нарезанные буферы фиксированного размера) и делают примитивы разбора потока с учётом перехода между страничками. Или заранее выделяют много памяти большим куском.

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

распарсить xml кусками не представляется возможным

Как это не представляется? SAX парсеры как раз позволяют читать xml кусками. Да, они не верифицируют валидность, но это вполне себе решение для потокового чтения

anonymous
()

Сохраняй файл, проверяй на ошибки записи/чтения.

7. Rule: The return value of non-void functions must be checked by each calling function, and the validity of parameters must be checked inside each function.

PHPFan
()

Парсить налету по кускам (SAX)

slovazap ★★★★★
()

Загонять кусками XML в SAX парсер? Только надо так чтобы он не отваливался на malformed xml, а ждал пока не приедет следующий кусок.

Dark_SavanT ★★★★★
()

суперстабильная система

закончиться память посыпаться диск посыпаться mysql база

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

anonymous
()

Буфер статического размера как-то плохо вяжется с неизвестным размером xml.

А классический подход - увеличивать размер буфера в полтора раза пока не влезет файл - не?

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

увеличивать размер буфера в полтора раза

Это и есть realloc.

Не, можно его заменить на malloc+memcpy+free, но где-то тут подвох :D

anonymous
()

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

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

и ты не написал главное, сбой-то каким образом должен быть обработан?

drsm ★★
()

Есть неизвестного размера (2 - 618 кб (возможно больше)) принимаемый через LAN xml. Возникла необходимость построить суперстабильную систему, для этого пришли к выводу что надо внедрять MISRA-C. А она запрещает realloc. Как быть с принимаемой xml? Буфер статического размера как-то плохо вяжется с неизвестным размером xml. А распарсить xml кусками не представляется возможным.

Отправлять принимаемые байты в файл? А если накрылся диск? На серваке где крутится демон может: закончиться память (стабильно раз в 2-3 дня), посыпаться диск (раз в 2-3 месяца), посыпаться mysql база (раз в 2-3 недели). Серваков 1000+, поэтому вышеперечисленные события случаются каждый день.

Что посоветуете?

могу посоветовать разогнать всех к чёртовой матери.

программисты не видят иных решений кроме «пихать текст в неразрывный кусок памяти», инженеры не рассчитали железо, архитектор влупил mysql для _супер_надёжной_системы_.

а они стандарты внедряют. Внедрятели :-)

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

это вполне себе решение для потокового чтения

А что делать с результатом разбора? Он же, скорее всего, тоже не фикисрованного размера. Все равно придется или сразу захватывать куски памяти (и отбрасывать слишком большие документы) или реаллоцировать.

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

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

На сервере кроме этого демона еще трансферы контента, различные обработчики, snmp-демоны и проч.

Диски крашатся потому что современное производство дисков - 2 года жизни от силы. Серверов 1000+, вот и выходят частые поломки.

сбой-то каким образом должен быть обработан?

А откуда ему взяться? Если не юзать realloc и отбрасывать невалидные xml?

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

Можешь пояснить? Ты про то, что ОС может выделить больше памяти, чем есть на самом деле, а уже по мере необходимости (в момент записи) производить реальный маппинг? Соответственно, если памяти не хватит, то может придти OOM-killer или начаться своппинг.

Ну так если интересует стабильность, то первым делом надо настроить ОС таким образом, чтобы такой фигни не было. Ибо куча в том числе системных приложений рассчитывает, что если malloc вернул не null, то всё хорошо.

Если же эта настройка ломает какие-то приложения, то они по дефолту не являются безопасными и надёжными, а значит какие бы стандарты ты не внедрял, система суперстабильной уже не будет.

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

ну тогда универсальных вариантов нет, потому что даже поточный парсер можно удивить base64 блобом на пару гигабайт

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

Если же эта настройка ломает какие-то приложения

Эта настройка стоит по умолчанию во всех линуксах.

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

dev (dev*) разделы станут чище и лучше, если подобные вопросы и подобных пользователей в частности будут просто игнорировать за тупизну, неадекватность и проч

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

malloc может вернуть non-null а при попытки записи туда все обрушится.

Т.е. тебе malloc нельзя использовать? Хмм... Тогда можно выделять на стеке через alloca или VLA из C99, но это ничем не лучше, там тоже все может обрушиться, когда закончится стек. Или делать жирные глобальные или статические массивы и костылить свой malloc/realloc/free поверх них. Но там тоже может обрушиться, если закончится место в этих массивах. И даже если использовать запись в файлы, даже тогда все может обрушиться, место на диске ведь не бесконечно.

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

Согласно стандарту malloc можно юзать только при нчальный инициализации. После нее уже критична стабильная работа.

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

То что она стоит по умолчанию не значит, что её нельзя изменить на нужную. Если хочется делать надёжную систему, то надо делать надёжным всё - начиная от приложения и заканчивая самой ОС.

Ибо даже если конкретно твоё приложение не упадёт, но навернётся какой-нибудь systemd из-за того, что сделал неудачный malloc, то всё равно один фиг всё встанет колом.

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

На сервере кроме этого демона еще трансферы контента, различные обработчики, snmp-демоны и проч. Диски крашатся потому что современное производство дисков - 2 года жизни от силы. Серверов 1000+, вот и выходят частые поломки.

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

Если вдруг сразу не заметно, то ~MISRA-C это стандарты для относительно простых встраиваемых систем которые обычно работают в спциально подготовленных изолированных железных окружениях с RTOS. Вам же, прежде чем бороться с аллокаторами, нужно сначала поработать над верхеуровневой архитектурой.

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

нет тут подвоха: realloc в точности так и поступает

сами подумайте: как realloc сможет расширять память без копирования, если следующий кусок памяти уже занят? а никак. то есть, в итоге, realloc — это выделение произвольного объёма заранее, а после исчерпания — тот же самый malloc+memcpy+free, причём буквально.

единственное, что в случае realloc выделение произвольного объёма заранее производится силами ОС (и то — стандартом не гарантировано) а в случае calloc — программист сам решает, сколько памяти нужно заранее выделить. как правило, второй подход даже эффективнее.

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

Значит ВЕСЬ линукс живет не по стандарту. Потому что под линуксом везде optimistic выделение. Возвращаем валидный указатель и падаем при попытки записи в него.

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

валидный
падаем

А запости кусок вашего кода, который вызывает такое поведение.

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

сами подумайте: как realloc сможет расширять память без копирования, если следующий кусок памяти уже занят? а никак. то есть, в итоге, realloc — это выделение произвольного объёма заранее

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

единственное, что в случае realloc выделение произвольного объёма заранее производится силами ОС (и то — стандартом не гарантировано)

Само по себе выделение памяти может быть вне кучи для больших кусков через ~mmap(), но, опять таки, резерва нет и последующие расширения осуществляются по факту возможности.

Если хочется резервирование буферов под дальнейший рост (нечто вида std::vector) или умного жонглирования адресным пр-вом для дешёвого наращивания непрерывной памяти средствами ОС, то всё это нужно делать руками, куча подобными задачами не занимается.

mashina ★★★★★
()

Отправлять принимаемые байты в файл? А если накрылся диск?

отправляй в файл, который находится в ramfs

На серваке где крутится демон может: закончиться память (стабильно раз в 2-3 дня)

1) доставить памяти 2) обрабатывать неудачную запись в случае нехватки памяти

посыпаться диск (раз в 2-3 месяца)

RAID на свои серваки рукожоп админ не смог поставить? хотспар диски, очевидно, для слабаков

посыпаться mysql база (раз в 2-3 недели)

при чем тут mysql? ты же его не просто так упомянул, давай выкладывай что там у вас за система

anonymous
()

а вообще, почитав тему, меня удивляет то, что никто не предлагает calloc(), а ТС не обратился к архитектору с претензией, что в ихней системе лютая нестабильность. И да, ты не описал задачу. Как твой распаршеный XML потом используется?

я бы вообще на месте ТС-а написал бы отдельный процесс-демон, который занимался бы парсингом. Таким образом, сократив возможные результаты работы до 2 вариантов: 1. данные обработаны; 2. ошибка

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

Учитывая предыдущую тему, тов. ТС Cargo-Cult-Programming занимается.

beastie ★★★★★
()

Построить суперстабильную систему - не вопрос. Когда потребуется построить суперпуперстабильную систему, тогда и обращайтесь.

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

а в чём разница между супер и суперпупер в контексте вопроса ТС?

Разница в «пупер» (англ. pooper).

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

в общем-то, я написал тоже самое, только другими словами )

anonymous
()

И ни одна лалка не предложила static array + свой аллокатор на его основе. Лор скатился в унылое говно.

anonymous
()

Буфер статического размера как-то плохо вяжется с неизвестным размером xml.

Статический набор (массив) буферов по 2 кб, и ведёшь структуры с записями что с такого буфера по такой - это одна xml'ка, с такого по такой - другая и т.п.

А распарсить xml кусками не представляется возможным.

Не понел? Нарезать то их можно?

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

в итоге, realloc — это выделение произвольного объёма заранее, а после исчерпания — тот же самый malloc+memcpy+free, причём буквально.

Справедливости ради, это не всегда так (по крайней мере в современном Linux).

Вот статья про некоторые особенности realloc http://blog.httrack.com/blog/2014/04/05/a-story-of-realloc-and-laziness/

и перевод на русский https://habrahabr.ru/company/abbyy/blog/238739/

Пишут, что если данных достаточно много(>= 128KB by default), при добавлении ничего не копируется, делается mremap

Deleted
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.