OberonCore https://forum.oberoncore.ru/ |
|
Кажется, ошибка в TextModels https://forum.oberoncore.ru/viewtopic.php?f=134&t=6811 |
Страница 1 из 1 |
Автор: | adimetrius [ Суббота, 23 Октябрь, 2021 21:50 ] |
Заголовок сообщения: | Кажется, ошибка в TextModels |
Коллеги, у меня завелась ошибка: иногда после закрытия документа и повторного открытия (в рамках одного запуска ББ) сохраненные изменения пропадали. Т.е. открываешь, изменяешь, закрываешь, открываешь - бац! изменения пропали. При этом в файле - измененный документ (видно через odcread). Немало времени и ядреных слов я потратил на восстановление пропащих авторских правок. В чем же дело? ББ гарантирует, что одному файлу соответствует один и тот же Files.File; зная это, я предполагал, что где-то в системе нет-нет, да и притаится паразитный указатель на файл, который не ликвидируется после закрытия окна с документом. У меня в ББ много "примочек" к редактору, которые кэшируют читателей TextModels.Reader (а внутри них есть иногда указатель на файл, из которого прочитан текст) и сканеры TextMappers.Scanner (а внутри них есть читатель). Я перерыл свои модули, перепроверил кэши, все аккуратно очистил - безрезультатно. Кажется, ошибка была в TextModels. Процедура PROCEDURE (text: TextModels.Model) NewReader (rd: TextModels.Reader) позволяет, для экономии памяти, передать rd, который будет переиспользован - т.е. можно взять чтеца, попользоваться, потом переподключить его к другому тексту и пользоваться дальше. Это описано в документации и немало используется в ББ. И вот я выяснил, что при переподключении важное поле Reader.run не переинициализируется. Это видно из анализа процедур TextModels.StdModel.NewReader и TextModels.StdReader.SetPos. А именно Reader.run после чтения текста из файла содержит указатель на TextModels.Piece, который содержит указатель на Files.File - это как раз и получается "фантомная" файловая переменная, которая незримо "висит" и не дает ББ видеть обновленную версию файла. Вот проверочный модуль. Он пишет в журнал имя "зацепленного" файла, а также показывает стек вызовов, в котором можно также убедиться в сохранении лишнего указателя. Код: MODULE BugReaders; IMPORT SYSTEM, TextModels, Views, Models, Files, Services, Log; TYPE Reader = POINTER TO RECORD eot*: BOOLEAN; attr*: INTEGER; char*: CHAR; view*: Views.View; w*, h*: INTEGER; base: INTEGER; (* base = Base() *) pos: INTEGER; (* pos = Pos() *) era: INTEGER; run: ANYPTR; (* era = base.era => Pos(run) + off = pos *) off: INTEGER; (* era = base.era => 0 <= off < run.len *) reader: Files.Reader (* file reader cache *) END; Piece = POINTER TO RECORD prev, next, len, attr: INTEGER; file: Files.File END; File = POINTER TO RECORD type-: Files.Type; init: BOOLEAN; state: INTEGER; name: ARRAY 256 OF CHAR; END; PROCEDURE Hack (rd: TextModels.Reader); VAR nm: ARRAY 64 OF CHAR; rdr: Reader; pc: Piece; f: File; BEGIN Services.GetTypeName(rd, nm); IF nm # "TextModels.StdReader" THEN Log.String("~(rd IS TextModels.StdReader"); Log.Ln ELSE rdr := SYSTEM.VAL(Reader, rd); IF rdr.run = NIL THEN Log.String(".run = NIL"); Log.Ln ELSE Services.GetTypeName(rdr.run, nm); IF nm # "TextModels.Piece" THEN Log.String("~(rd.run IS TextModels.Piece"); Log.Ln ELSE pc := SYSTEM.VAL(Piece, rdr.run); IF pc.file = NIL THEN Log.String("rd.run.file = NIL"); Log.Ln ELSE f := SYSTEM.VAL(File, pc.file); Log.String("rd.run.file.name = "); Log.String(f.name); Log.Ln END END END END END Hack; PROCEDURE Do*; VAR rd: TextModels.Reader; t: Models.Model; v: Views.View; BEGIN v := Views.OldView(Files.dir.This('System/Rsrc/'), 'Menus.odc'); t := v.ThisModel(); WITH t: TextModels.Model DO rd := TextModels.dir.New().NewReader(rd); Hack(rd); rd := t.NewReader(NIL); rd.Read; Hack(rd); rd := TextModels.dir.New().NewReader(rd); Hack(rd); HALT(0) END END Do; END BugReaders. (!) BugReaders.Do После BugReaders.Do в журнале - дважды имя файла System/Rsrc/Menus.odc, хотя должно быть лишь один. А вот поправка в TextModels.StdModel.NewReader, которая, кажется, должна и исправляет ошибку: Код: PROCEDURE (t: StdModel) NewReader (old: Reader): Reader; VAR rd: StdReader; BEGIN StdInit(t); IF (old # NIL) & (old IS StdReader) THEN rd := old(StdReader) ELSE NEW(rd) END; IF rd.base # t THEN rd.base := t; rd.era := -1; (*==>*) rd.run := NIL; (*<==*) rd.SetPos(0) ELSIF rd.pos > t.len THEN rd.SetPos(t.len) END; rd.eot := FALSE; RETURN rd END NewReader; С этой поправкой BugReaders.Do, как и ожидается, выдает имя файла System/Rsrc/Menus.odc только один раз. И у меня вроде пропали фантомные файлы. Что скажете? Прошу поразмыслить, попробовать, и в конечном итоге - предлагаю включить поправку в ББ. |
Автор: | Илья Ермаков [ Воскресенье, 24 Октябрь, 2021 01:58 ] |
Заголовок сообщения: | Re: Кажется, ошибка в TextModels |
Хм, на Wine периодически сталкиваемся с ошибкой, что нельзя сохранить документ (не удаётся записать файл). При повторном Ctrl-S, как правило, норм. Похоже, это ноги оттуда же растут. |
Автор: | Иван Денисов [ Воскресенье, 24 Октябрь, 2021 07:55 ] |
Заголовок сообщения: | Re: Кажется, ошибка в TextModels |
Аргументы выглядят убедительно. Вот тут ещё есть некий буфер, судя по комментарию, который вероятно также лучше очищать во избежание проблем? Вложение:
|
Автор: | Борис Рюмшин [ Воскресенье, 24 Октябрь, 2021 11:41 ] |
Заголовок сообщения: | Re: Кажется, ошибка в TextModels |
Илья Ермаков писал(а): Хм, на Wine периодически сталкиваемся с ошибкой, что нельзя сохранить документ (не удаётся записать файл). При повторном Ctrl-S, как правило, норм. Похоже, это ноги оттуда же растут. Нет, это связано, на сколько я помню, с особенностями работы самого Wine. |
Страница 1 из 1 | Часовой пояс: UTC + 3 часа |
Powered by phpBB® Forum Software © phpBB Group https://www.phpbb.com/ |