Гарантируются ли классы одинаковой организации в памяти между запусками программы? - PullRequest
1 голос
/ 29 января 2012

Я пытаюсь внедрить функцию сохранения / загрузки в мою маленькую игру.Для этого у меня есть центральный класс, в котором хранятся все важные переменные игры, такие как позиция и т. Д. Затем я сохраняю этот класс в виде двоичных данных в файл.Затем просто загрузите его обратно для функции загрузки.Кажется, это работает БОЛЬШЕ времени, но если я изменю некоторые вещи, то попытка сохранить / загрузить программу приведет к сбою с нарушениями доступа к памяти.Итак, гарантируется ли, что классы имеют одинаковую структуру в памяти при каждом запуске программы, или данные могут быть расположены случайным образом, как структура?

Ответ Иисусу - я имею в виду данные внутри класса, так чтоесли я сохраню класс на диск, когда я его снова загрузлю, все вернется обратно.

Сохранить

fout.write((char*) &game,sizeof Game);

Загрузить

fin.read((char*) &game, sizeof Game);

Ответы [ 4 ]

4 голосов
/ 29 января 2012

Ваш подход чрезвычайно хрупок. Со многими ограничениями это может работать. Этим ограничениям не стоит подвергать своих пользователей (или себя!) В типичных случаях.

Некоторые ограничения:

  • Никогда не ссылаться на внешнюю память (например, указатель или ссылку)
  • Запретить изменения / различия ABI. Общий случай: расположение памяти и естественное выравнивание на 32 против 64 будет отличаться. Пользователю понадобится новая «игра» для каждого ABI.
  • Не совместим с порядком байтов.
  • Изменение макетов вашего типа сломает вашу игру. Изменение параметров компилятора может сделать это.
  • Вы в основном ограничены данными POD.
  • Используйте смещения вместо указателей для ссылки на внутренние данные (эта ссылка будет в непрерывной памяти).

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

Поскольку это тег C ++, " boost - Serialization " будет хорошей отправной точкой. Он хорошо проверен и анализирует многие сложности для вас.

2 голосов
/ 29 января 2012

Даже если это сработает, просто не делайте этого. Определите формат файла на уровне байтов и напишите разумные функции «конвертировать в формат файла» и «конвертировать из формата файла». Вы на самом деле знаете формат файла. Вы сможете продлить его. Более новые версии программы смогут читать файлы из более старых версий. И вы сможете обновлять свою платформу, создавать инструменты и классы, не опасаясь, что ваша программа будет аварийно завершена.

1 голос
/ 29 января 2012

Да, классы и структуры будут иметь одну и ту же компоновку в памяти при каждом запуске вашей программы. Хотя я не могу сказать, соблюдает ли это стандарт. Машинный код, сгенерированный компиляторами C ++, использует «жестко запрограммированные» смещения для доступа к полям типов, поэтому они являются фиксированными. Реально макет изменится только в том случае, если вы измените определение класса C ++ (размеры полей, порядок, виртуальные методы и т. Д.), Скомпилируете с другим компилятором или измените параметры компилятора.

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

[править]

Чтобы ответить на собственное изменение, не делайте этого с вашим объектом "Игра"! Он, безусловно, имеет указатели на другие объекты, и эти объекты больше не будут существовать в памяти или будут где-то еще, когда вы перезагрузите свой файл.

0 голосов
/ 29 января 2012

Возможно, вы захотите взглянуть на это .

Классы не обязательно имеют одинаковую структуру в памяти, так как указатели могут указывать на разные места в памяти при каждом создании класса.

Однако без публикации кода трудно с уверенностью сказать, где проблема.

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