![]() |
![]() ![]() ![]() ![]() ![]() |
![]() |
Serialization - Special ConsiderationsBoost , ,
Object TrackingDepending on how the class is used and other factors, serialized objects may be tracked by memory address. This prevents the same object from being written to or read from an archive multiple times. These stored addresses can also be used to delete objects created during a loading process that has been interrupted by throwing of an exception.Это может вызвать проблемы в прогамах, где копии разных объектов сохраняются с одного адреса.< >В этом случае данные, подлежащие сохранению, находятся в стеке. Каждая итерация цикла обновляет значение в стеке. Таким образом, хотя данные изменяют каждую итерацию, адрес данных не изменяется. Если a [i] представляет собой массив объектов, отслеживаемых по адресу памяти, библиотека пропустит хранение объектов после первого, поскольку предполагается, что объекты по тому же адресу на самом деле являются одним и тем же объектом.Чтобы помочь обнаружить такие случаи, операторы выходных архивов ожидают, что будут переданы< Учитывая это, приведенный выше код вызовет утверждение компиляции времени. Очевидным исправлением в этом примере является использование< >, которое будет компилироваться и работать без проблем. Использование<const >операторами выходных архивов гарантирует, что процесс сериализации не изменит состояние серийируемых объектов. Попытка сделать это представляла бы собой расширение понятия спасения государства с каким-то неочевидным побочным эффектом. Это почти наверняка будет ошибкой и вероятным источником очень тонких ошибок.К сожалению, проблемы с реализацией в настоящее время препятствуют обнаружению такого рода ошибок, когда элемент данных обернут в виде пары имён и значений. Аналогичная проблема может возникнуть, когда различные объекты загружаются по адресу, отличному от конечного местоположения:< >В этом случае адрес<x >является тем, который отслеживается, а не адресом нового элемента, добавленного в набор. Оставшись без внимания, это нарушит функции, которые зависят от отслеживания, такие как загрузка объекта через указатель. В программу будут введены тонкие баги. Это может быть решено путем изменения вышеупомянутого кода таким образом:< >Это позволит скорректировать информацию отслеживания таким образом, чтобы она отражала место последнего упокоения перемещаемой переменной, и тем самым устранить вышеупомянутую проблему.Если априори известно, что никакие значения указателей не дублируются, накладные расходы, связанные с отслеживанием объектов, могут быть устранены путем соответствующей установки признака сериализации класса отслеживания объектов. По умолчанию не отслеживаются типы данных, обозначенные примитивными чертой сериализации классауровня реализации. Если желательно отслеживать общий примитивный объект через указатель (например,< Возможно, мы захотим отслеживать адреса, даже если объект никогда не сериализуется через указатель. Например, виртуальный базовый класс должен быть сохранен / загружен только один раз. Установив эту черту сериализации< Для реализации этой возможности объявляетсявспомогательный объект, связанный с текущим архивом, который может использоваться для хранения контекстной информации, относящейся к конкретному алгоритму сериализации типа.< Могут быть созданы помощники для сохранения и загрузки архивов. В одной и той же программе может быть несколько разных помощников или один и тот же помощник, созданный отдельно от разных частей программы. Это то, что делает помощь_instance_id необходимой. В принципе это может быть любое уникальное целое число. На практике проще всего использовать адрес содержащейся в нем функции сериализации. Приведенный выше пример использует эту технику. .Отключение отслеживания и сериализации информации о классе приведет к чистому встроенному коду шаблона, который в принципе может быть оптимизирован до простой записи / чтения потока.Устранение всех накладных расходов на сериализацию таким образом обходится дорого. После того, как архивы будут выпущены для пользователей, признаки сериализации класса не могут быть изменены без признания старых архивов недействительными. Включение информации о классе в архив гарантирует, что она будет читаемой в будущем, даже если определение класса будет пересмотрено. Легковесная структура, такая как пиксель дисплея, может быть объявлена в заголовке, таком как:< >Переносимость архиваНесколько классов архивов создают свои данные в виде текста или переносного двоичного формата. Должна быть возможность сохранить такой класс на одной платформе и загрузить его на другую. Это зависит от нескольких условий.ЧислаАрхитектура машинного считывания архива должна содержать сохраненные данные. Например, компилятор gcc резервирует 4 байта для хранения переменной типа<wchar_t >, в то время как другие компиляторы резервируют только 2 байта. Таким образом, возможно, что может быть записано значение, которое не может быть представлено программой загрузки. Это довольно очевидная ситуация и легко обрабатывается с помощью численных типов вСпециальный интегральный тип< ЧертыДругая потенциальная проблема иллюстрируется следующим примером:< >Если<my_wrapper >использует черты сериализации по умолчанию, может возникнуть проблема. С признаками по умолчанию каждый раз, когда в архив добавляется новый тип, добавляется бухгалтерская информация. Таким образом, в этом примере архив будет включать такую бухгалтерскую информацию для<my_wrapper<wchar_t> >и для<my_wrapper<short_unsigned> >. Или нет? А как насчет компиляторов, которые рассматривают<wchar_t >как синоним<unsigned short >? При этом существует только один отдельный тип — не два. Если архивы передаются между программами с компиляторами, которые отличаются по своей обработке<wchar_t >, то операция загрузки выйдет из строя катастрофическим образом.Одним из средств для этого является присвоение шаблону< Еще один способ избежать этой проблемы — присвоить всем специализациям шаблона< Бинарные архивыСтандартный поток i/o на некоторых системах расширит символы линейного питания до обратной передачи/линейного питания на выходе. Это создает проблему для бинарных архивов. Самый простой способ справиться с этим — открыть потоки для бинарных архивов в «бинарном режиме» с помощью флага<ios::binary >. Если этого не сделать, сгенерированный архив будет нечитаемым.К сожалению, не было найдено способа обнаружить эту ошибку до загрузки архива. Debug builds будет утверждать, когда это будет обнаружено, так что это может быть полезно для обнаружения этой ошибки. XML АрхивыXML архивы представляют собой несколько особый случай. XML-формат имеет вложенную структуру, которая хорошо отображает шаблон «рекурсивный посетитель класса», используемый системой сериализации. Однако XML отличается от других форматов тем, что для каждого элемента данных требуется имя. Наша цель состоит в том, чтобы добавить эту информацию в спецификацию сериализации класса, при этом позволяя использовать код сериализации с любым архивом. Это достигается требованием, чтобы все данные, сериализованные в XML-архив, были сериализованы какпара имени-значения. Первый элемент - это имя, которое будет использоваться в качестве XML-метки для элемента данных, а второй - ссылка на сам элемент данных. Любая попытка сериализовать данные, не завернутые вименную пару, будет заблокирована во время компиляции. Система реализована таким образом, что для других классов архивов сериализуется только ценностная часть данных. Часть имени отбрасывается во время компиляции. Таким образом, всегда используяпары значений имени, можно гарантировать, что все данные могут быть сериализованы для всех классов архивов с максимальной эффективностью.Сериализация экспортного классаВ другом местев этом руководстве мы описали<BOOST_CLASS_EXPORT >. Экспорт подразумевает две вещи:
< Обратите внимание, что для имплементации этой функциональности требуется, чтобы макрос< >Это будет справедливо независимо от того, является ли код частью отдельного исполняемого файла, статической библиотеки или динамической или общей библиотеки.Включение< Эта система имеет определенные последствия для размещения кода в статических или общих библиотеках. Размещение< Строго говоря, экспорт не должен быть необходим, если вся последовательность указателей происходит через наиболее производный класс. Тем не менее, для того, чтобы обнаружить, что было бы катастофической ошибкой, библиотека улавливает ВСЕ сериализации через указатель на полиморфный класс, который не экспортируется или не регистрируется иным образом. Поэтому на практике будьте готовы зарегистрировать или экспортировать все классы с одной или несколькими виртуальными функциями, которые сериализуются через указатель. Обратите внимание, что реализация этой функциональности зависит от конкретных расширений поставщика языка C++. Таким образом, нет гарантированной переносимости программ, которые используют этот объект. Тем не менее, все компиляторы C++, которые тестируются с ускорением, обеспечивают необходимые расширения. Библиотека содержит дополнительные декларации, требуемые каждым из этих составителей. Разумно ожидать, что будущие компиляторы C++ будут поддерживать эти расширения. Статические библиотеки и сериализацияКод для сериализации типов данных может быть сохранен в библиотеках так же, как и для остальной части реализации типа. Это хорошо работает и может сэкономить огромное количество времени на компиляцию.
demo_pimpl.cpp >,<demo_pimpl_A.cpp >и<demo_pimpl_A.hpp >, где реализация сериализатона находится в статической библиотеке, полностью отдельной от основной программы.DLLS - Сериализация и соединение времени выполненияКод сериализации может быть размещен в библиотеках для соединения во время выполнения. То есть код может быть размещен в DLLS (Windows) Shared Libraries (*nix) или в статических библиотеках, а также в главном исполняемом файле. Лучшая методика та же, что описана выше для библиотек. Тестовый пакет библиотеки сериализации включает в себя следующие программы для иллюстрации того, как это работает:< Также включены< Для достижения наилучших результатов напишите свой код в соответствии со следующими рекомендациями:
ПлагиныДля реализации библиотеки требовались различные средства манипулирования типами во время выполнения. Это<extended_type_info >для связывания классов с внешними идентифицирующими струнамиGUIDи<void_cast >для литья между указателями родственных типов. Для завершения функциональности<extended_type_info >добавлена возможность конструирования и уничтожения соответствующих типов. Чтобы использовать эту функциональность, необходимо указать, как создается каждый тип. Это должно быть сделано в то время, когда класс экспортируется. Таким образом, более полным примером кода выше будет:< >При этом можно построить, сериализовать и уничтожить класс, о котором известно толькоГИДи базовый класс.МногопоточностьОсновная цель сериализации будет конфликтовать с несколькими потоками одновременного написания / чтения из / в один экземпляр открытого архива. Реализация библиотеки предполагает, что приложение избегает такого расположения.Однако одновременное написание/прочтение различных архивов в различных задачах допускается, поскольку каждый экземпляр архива (почти) полностью независим от любого другого экземпляра архива. Единственной совместно используемой информацией являются таблицы некоторых типов, которые были реализованы с использованием безблокировочной защиты потока.< Эта однотонная реализация гарантирует, что вся эта общая информация инициализируется при загрузке модуля кода, который содержит ее. Библиотека сериализации заботится о том, чтобы эти структуры данных не были впоследствии изменены. Единственная проблема может возникнуть, если код загружается / выгружается, в то время как другая задача - сериализация данных. Это может произойти только для типов, сериализация которых реализована в динамически загруженной/незагруженной DLL или общей библиотеке. Если же этого избежать, то
ОптимизацияВ критических приложениях производительности, которые сериализуют большие наборы смежных данных однородных типов, нужно избегать накладных расходов на сериализацию каждого элемента по отдельности, что является мотивацией для.<array >Обертка. Функции сериализации для типов данных, содержащих смежные массивы однородных типов, таких как<std::vector >,<std::valarray >или<boost::multiarray >, должны сериализовать их с использованием.<array >обертка для использования этих оптимизаций. Архивные типы, которые могут обеспечить оптимизированную сериализацию для смежных массивов однородных типов, должны реализовывать их, перегружая сериализацию обертки<array >, как это делается для бинарных архивов.Архивные исключенияБезопасность исключения& копия; Авторское правоРоберт Рэми2002-2004. Распространяется под лицензией Boost Software License, версия 1.0. (См. сопроводительный файл LICENSE_1_0.txt или копию по адресу http://www.boost.org/LICENSE_1_0.txt) Статья Serialization - Special Considerations раздела может быть полезна для разработчиков на c++ и boost. Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта. :: Главная :: ::
|
||||||
©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007 |