Научился делать "настоящие" immutable объекты.
Через перекрытие NewInstance + VirtualAlloc + VirtualProtect.
Перекрываем NewInstance - там аллоцируем память через VirtualAlloc (там есть тонкости с размером страниц и стратегией выделения памяти).
Потом заполняем поля объекта в конструкторе. И "закрываем" доступ на запись через VirtualProtect + Page_ReadOnly - в AfterCreate.
Потом в FreeInstance (или destroy - тут есть тонкости) опять разрешаем доступ.
Получаем гарантировано неизменяемые объекты.
Например для паттерна flyweight.
Или например для случая:
ConstString = interface
Function S: PChar;
End;
Ничто не мешает сделать так:
Var Cs: ConstString;
Cs := Factory.GetCs('value');
Cs.S^ := 'xxx';
Т.е "кишки" объекта будут испорчены.
А вот virtualProtect + page_readonly - решают эту проблему.
Через перекрытие NewInstance + VirtualAlloc + VirtualProtect.
Перекрываем NewInstance - там аллоцируем память через VirtualAlloc (там есть тонкости с размером страниц и стратегией выделения памяти).
Потом заполняем поля объекта в конструкторе. И "закрываем" доступ на запись через VirtualProtect + Page_ReadOnly - в AfterCreate.
Потом в FreeInstance (или destroy - тут есть тонкости) опять разрешаем доступ.
Получаем гарантировано неизменяемые объекты.
Например для паттерна flyweight.
Или например для случая:
ConstString = interface
Function S: PChar;
End;
Ничто не мешает сделать так:
Var Cs: ConstString;
Cs := Factory.GetCs('value');
Cs.S^ := 'xxx';
Т.е "кишки" объекта будут испорчены.
А вот virtualProtect + page_readonly - решают эту проблему.
Комментариев нет:
Отправить комментарий