Страница 1 из 2

Эти странные динамические строки

Добавлено: 25 Октябрь 2018, 9:40
Игорь Столяров
Привет всем !

Поясните пожалуйста, или я чего-то не понимаю, или оно совсем не того … :( Пример:

Код: Выделить всё

Loc:Buffer  &IDynStr

  Code
 
   Loc:Buffer &= NewDynStr()
   If ~(Loc:Buffer &= Null)
      Loc:Buffer.Cat('Привет ромашки !')
      Message(Loc:Buffer.Str())
      DisposeDynStr(Loc:Buffer)
   end
 
   ! А теперь самое интересное
   If ~(Loc:Buffer &= Null)
      Message('Указатель на динамическую строку всё равно существует ?!') 
      DisposeDynStr(Loc:Buffer)  ! И ВЫЛЕТ ИЗ ПРОГРАММЫ (ИНОГДА МОЛЧА, ИНОГДА С GPF)
   end
Что я делаю не так ? Почему при освобождении памяти указатель на строку всё равно существует ?
Заранее спасибо ...

Эти странные динамические строки

Добавлено: 25 Октябрь 2018, 10:00
Admin
Из за этой хрени я не пользуюсь для IDynStr проверкой на NULL а просто стараюсь четко соблюдать последовательность.
Если за DisposeDynStr(Loc:Buffer) добавить DISPOSE(Loc:Buffer) переменная обнулится. Но не думаю что это правильно :)

Эти странные динамические строки

Добавлено: 25 Октябрь 2018, 10:05
Игорь Столяров
Admin писал(а): 25 Октябрь 2018, 10:00добавить DISPOSE(Loc:Buffer)
Явно применять Dispose() опасно даже для несуществующего указателя на простой тип данных …
Здесь скорее надо заменить:

Код: Выделить всё

  DisposeDynStr(Loc:Buffer)
на

Код: Выделить всё

  DisposeDynStr(Loc:Buffer)
  Loc:Buffer &= NULL
Но как-то это странно и непонятно. Совсем. :(

Эти странные динамические строки

Добавлено: 25 Октябрь 2018, 11:47
Yufil
А кто сказал, что при ликвидации объекта должна очищаться ссылка на него? Нет никакой возможности определить, где эта ссылка хранится и нет ли других ссылок на тот же самый объект.

Эти странные динамические строки

Добавлено: 25 Октябрь 2018, 12:04
Игорь Столяров
Yufil писал(а): 25 Октябрь 2018, 11:47где эта ссылка хранится и нет ли других ссылок на тот же самый объект.
Да, но с простыми типами данных это работает именно так …
Например несколько указателей может указывать на одну строку (String).
При применении Dispose() к любому из указателей, все остальные можно проверить на NULL и не нарываться на проблемы.
А здесь другое … DisposeDynStr() оставляет "живым" указатель и любое обращение к нему заканчивается крахом. :(

Эти странные динамические строки

Добавлено: 25 Октябрь 2018, 13:17
Yufil
У меня когда-то не срослось с DynStr/Any, падало на Prop:Use, неожиданные проблемы с Evaluate и т.д. пришлось свой класс писать. Наверное, не разобрался как следует. Как в анекдоте - ложечки нашлись, но осадок остался :)

Эти странные динамические строки

Добавлено: 25 Октябрь 2018, 13:27
Игорь Столяров
Ну написать свой класс работы с безразмерными строками не проблема. :)
У меня тоже есть загрузка в строку по HTTP файла неведомого размера.
А с IDynStr вроде как всё готово и встроено - грех не пользоваться. Однако есть нюансы. :)

Эти странные динамические строки

Добавлено: 25 Октябрь 2018, 13:50
Дед Пахом
Игорь Столяров писал(а): 25 Октябрь 2018, 9:40Почему при освобождении памяти указатель на строку всё равно существует ?
Указатель, положим, не на строку. И где в документации написано, что DisposeDynStr должен что-то обнулять?

Эти странные динамические строки

Добавлено: 25 Октябрь 2018, 15:56
vic7tar
С DynStr не имел дела, но напрашивается вопрос - а почему не сделано как с обычным Dispose -> одновременно освобождается память и обнуляется указатель?

Эти странные динамические строки

Добавлено: 25 Октябрь 2018, 16:21
Игорь Столяров
Дед Пахом писал(а): 25 Октябрь 2018, 13:50что DisposeDynStr должен что-то обнулять
Ну как бы DisposeDynStr() освобождает память занимаемую структурой IDynStr, на которую указывает указатель.
После этого любые обращения по указателю - ошибочны (точнее даже катастрофичны).
Вполне логично ожидать, что это будет как-то обозначено, например установкой самого указателя в NULL (по аналогии с Dispose()).
Иначе просто невозможно проверить в каком состоянии структура IDynStr и можно ли к ней обращаться ...

Эти странные динамические строки

Добавлено: 26 Октябрь 2018, 16:08
Игорь Столяров
vic7tar писал(а): 25 Октябрь 2018, 15:56С DynStr не имел дела, но напрашивается вопрос
А напрасно ! Прелюбопытнейший прибамбас, доложу я Вам … :)

Зацикливаем, например вот такой код и смотрим через диспетчер задач, как приложение медленно,
но верно начинает поджирать память:

Код: Выделить всё


  Loop ...
     MySlip &= NewDynStr()
     MySlip.Cat('Какой-то длинный предлинный текст')
     !!! MySlip.Kill
     DisposeDynStr(MySlip)
  end
  
Убираем комментарий и всё приходит в норму - расход памяти на уровне погрешности наблюдения (плюс / минус)…
Почему оно всё так сделано ? Это вопрос грустной философии Clarion … ;)

Эти странные динамические строки

Добавлено: 26 Октябрь 2018, 16:13
Дед Пахом
Игорь Столяров писал(а): 26 Октябрь 2018, 16:08Убираем комментарий и всё приходит в норму
Вот за это спасибо, пойду везде Kill поставлю (интересно, Trunc(0) тот же эффект даёт?).

Эти странные динамические строки

Добавлено: 26 Октябрь 2018, 16:17
Игорь Столяров
Дед Пахом писал(а): 26 Октябрь 2018, 16:13(интересно, Trunc(0) тот же эффект даёт?).
Кто же его знает как оно работает … Это же не LibSrc, а где-то в недрах RTL всё происходит …
Нам дано лишь наблюдать данный феномен посредством эксперимента … ;)
Могу предположить, что Kill() и Trunc(0) просто сводятся к записи Chr(0) в первую позицию строки.

Эти странные динамические строки

Добавлено: 26 Октябрь 2018, 17:56
vic7tar
Игорь Столяров писал(а): 26 Октябрь 2018, 16:08А напрасно ! Прелюбопытнейший прибамбас, доложу я Вам … :)
Не спасибо за рекламу - обойдусь.
Ну поставили Kill, ну обнулили строку, а как это связано с началом поста?

Эти странные динамические строки

Добавлено: 26 Октябрь 2018, 18:17
Игорь Столяров
vic7tar писал(а): 26 Октябрь 2018, 17:56а как это связано с началом поста
Никак не связано. Время идёт, вопросы решаются, проблемы меняются и т.д.
А вот с темой данной группы сообщений связано самым непосредственным образом.
Зачем плодить разделы, если сказка-то одна и та же ? :)

Кстати, то что метод ОЧИСТКИ строки называется IDynStr.Kill() косвенно свидетельствует, что либо сам IDynStr
появился намного раньше классов ABC, либо то, что его делал программер не знакомый с именами классов в ABC. ;)