Время жизни управляемых строк

Вопросы программирования на Free Pascal, использования компилятора и утилит.

Модератор: Модераторы

Время жизни управляемых строк

Сообщение runewalsh » 07.05.2015 19:52:52

Временные строки живут до конца функции, даже не хотя бы блока begin/end, в котором созданы. Поэтому если происходит longjmp, они утекают, и единственное, что можно с этим сделать, это вынести всё перед потенциальным лонгджампом во вложенную функцию (ну или не вложенную) — по выходу из неё временные переменные уничтожатся и можно лонгджампаться спокойно.

Это настраивается/отключается?

Где-то читал, что такое поведение необходимо, чтобы можно было приводить временные строки к PChar. Но я никогда не привожу временные строки к PChar, живущему дольше выражения, в котором он участвует, или вызова функции, аргументом которой является, ведь это опасно и не нужно!

Код: Выделить всё
{$mode objfpc}
{$longstrings+}

uses
  heaptrc;

  function StrA: string;
  begin
    result := 'StrA';
  end;

  function StrB: string;
  begin
    result := 'StrB';
  end;

  procedure ProcessString(const s: string);
  begin
    writeln(s);
  end;

  procedure Leaks(var cp: jmp_buf);
  begin
    begin ProcessString(StrA + StrB); end;
    longjmp(cp, 1); // Бдыщ! Теперь временная строка для StrA + StrB будет жить вечно.
  end;

  procedure DontLeaks(var cp: jmp_buf);
    procedure WorkWithTemporaries;
    begin
      ProcessString(StrA + StrB);
    end; // Здесь временная строка освободилась. Она бы освободилась, даже если бы я вернул на неё PChar.
         // Так зачем ей вообще жить дольше скобок?
  begin
    WorkWithTemporaries;
    longjmp(cp, 1);
  end;

var
  cp: jmp_buf;

begin
  if setjmp(cp) = 0 then Leaks(cp);
  if setjmp(cp) = 0 then DontLeaks(cp);
end.

→ 2 memory blocks allocated, 1 memory blocks freed.
Аватара пользователя
runewalsh
энтузиаст
 
Сообщения: 579
Зарегистрирован: 27.04.2010 00:15:25

Re: Время жизни управляемых строк

Сообщение скалогрыз » 07.05.2015 20:19:42

runewalsh писал(а):Это настраивается/отключается?

разве что сделать из управляемых строк, неуправляемые shortstring? :)

или писать уже ручками?
Код: Выделить всё
procedure Leaks(var cp: jmp_buf);
var
  t : string;
  begin
   t:=StrA + StrB;
    begin ProcessString(t); end;
    t:='';
    longjmp(cp, 1); // Бдыщ! Теперь временная строка для StrA + StrB будет жить вечно.
  end;

скалогрыз
долгожитель
 
Сообщения: 1803
Зарегистрирован: 03.09.2008 02:36:48

Re: Время жизни управляемых строк

Сообщение runewalsh » 07.05.2015 20:43:23

скалогрыз
Да, так и делаю, если совсем уж неудобно вырывать из контекста в отдельную процедуру, но треш ведь.
Аватара пользователя
runewalsh
энтузиаст
 
Сообщения: 579
Зарегистрирован: 27.04.2010 00:15:25

Re: Время жизни управляемых строк

Сообщение скалогрыз » 07.05.2015 20:50:14

runewalsh писал(а):Да, так и делаю, если совсем уж неудобно вырывать из контекста в отдельную процедуру, но треш ведь.

отказываться от longjmp-ов и писать exception-ами ?
скалогрыз
долгожитель
 
Сообщения: 1803
Зарегистрирован: 03.09.2008 02:36:48

Re: Время жизни управляемых строк

Сообщение runewalsh » 07.05.2015 22:17:41

скалогрыз
Я же не настолько извращенец, чтобы лонгджампаться самому. Лонгджампается Lua. Хотя нет, был неправ, в моём случае ошибки разруливаются не longjmp, а C++-исключениями, которые, впрочем, тоже плевать хотели на мой стек. По сути там за исполнение чего-то под импровизированным try-except отвечает единственная функция, и ещё одна за raise — их можно было бы переписать с коллбэком, задаваемым со стороны FPC и использующим FPC-шные исключения, но мне лень ^^, да и проблемы-то и не было бы, если бы в срезаемом куске стека не оставалось автоматических объектов, которых я не просил.
Аватара пользователя
runewalsh
энтузиаст
 
Сообщения: 579
Зарегистрирован: 27.04.2010 00:15:25

Re: Время жизни управляемых строк

Сообщение скалогрыз » 07.05.2015 22:38:35

runewalsh писал(а):Лонгджампается Lua. Хотя нет, был неправ, в моём случае ошибки разруливаются не longjmp, а C++-исключениями, которые, впрочем, тоже плевать хотели на мой стек.

Аааааа вроде бы понял. Хотя нет, ты всё-таки отключил C++ исключения?

Т.е. вместо использования FPC экспешена через lua_atpanic, ты используешь то, что есть в C-Lua.
скалогрыз
долгожитель
 
Сообщения: 1803
Зарегистрирован: 03.09.2008 02:36:48

Re: Время жизни управляемых строк

Сообщение alexs » 07.05.2015 22:39:20

Господа - а в чём сокральный смысл этого longjmp?
Исключительно чтобы прострелить себе ногу?

PS
Напоминает анекдот про японскую бензопилу и сибирского мужика...
Аватара пользователя
alexs
долгожитель
 
Сообщения: 4064
Зарегистрирован: 15.05.2005 23:17:07
Откуда: г.Ставрополь

Re: Время жизни управляемых строк

Сообщение скалогрыз » 07.05.2015 22:44:39

alexs писал(а):Господа - а в чём сокральный смысл этого longjmp?
Исключительно чтобы прострелить себе ногу?

Си же! Там нету exception-ов, а иногда очень хочется плюнуть на всё и откатится куда надо.
Си-шники с тем же презрением смотрять на все языки более высокого уровня :)
скалогрыз
долгожитель
 
Сообщения: 1803
Зарегистрирован: 03.09.2008 02:36:48

Re: Время жизни управляемых строк

Сообщение runewalsh » 07.05.2015 23:24:56

скалогрыз писал(а):Т.е. вместо использования FPC экспешена через lua_atpanic

До PANIC дело доходить не должно и она здесь не поможет. Короче, так. В Lua бывают «call» (lua_call), «protected call» (lua_pcall) и «throw» (lua_error). Call бросает любые ошибки наружу (реализация тривиальна), PCall ловит ошибки и сообщает о них в месте своего вызова (реализация через try-catch или setjmp), а throw, собственно, бросает ошибку (реализация через longjmp или исключение языка). Panic — это throw вне pcall'а, таких в нормальной работе вообще не должно быть, кроме out of memory. Пользовательской реализации исключений не предусмотрено, дописать, по идее, несложно, но меня бы устраивали и те игнорирующие FPC-стек, что есть, если бы в последнем не оставались невидимые управляемые переменные.

FPC → Lua (1) → FPC (2) → Lua (3)

FPC-оболочка (2), сквозь которую может проброситься «чужеродное» исключение (3) → (1) (неважно, C++ throw или longjmp), достаточно «тонкая» и специфичная, чтобы перспектива никогда не вернуться не грозила утечкой ресурсов... не считая как раз «застрявших» в стеке временных строк, которые мне не просто не нужны, а вообще невидимы, так что даже руками нельзя занулить, но которые компилятор тем не менее не освобождает сразу.
Аватара пользователя
runewalsh
энтузиаст
 
Сообщения: 579
Зарегистрирован: 27.04.2010 00:15:25

Re: Время жизни управляемых строк

Сообщение скалогрыз » 08.05.2015 07:03:32

хм. Оказывается есть модификатор noreturn, которые по-идее указывает, что данная процедура не намерена что-либо вернуть, а наоборот потенциально может выкинуть код куда угодно. Как раз для longjmp или lua_error.
Но FPC 2.6.4 её упорно не понимает, так что придётся пробовать транк.

Хотя в документации и не сказано, что модификатор принудит компилятор осободить все managed типы, но логика вещей подсказывает, что это может быть именно так. (а если это в данный момент не так, то это можно будет сделат заявку на реализацию :) )
--
разве что свои реализации писать руководствуясь следующими правилами:
* любой вызов к lua из такой функции - должен быть pcall()
* не вызывать lua_error, даже если очень хочется.
* если вызывать lua_errоr, то не использовать управляемые типы (ansi/widestring, динамические массивы) вообще :)

Кстати, почему бы не использовать вложенные процедуры?
Код: Выделить всё
procedure NoMoreLeaks(var cp: jmp_buf);
 
   procedure _NoMoreLeaks;
   begin
      ProcessString(StrA + StrB);
    end;
  begin
    _NoMoreLeaks;
    longjmp(cp, 1); // Бдыщ! а временной строки для StrA + StrB уже не существует!
  end;

убого, конечно, но работает. Вся надежда на noreturn :)
скалогрыз
долгожитель
 
Сообщения: 1803
Зарегистрирован: 03.09.2008 02:36:48

Re: Время жизни управляемых строк

Сообщение скалогрыз » 15.05.2015 16:00:16

Не в тему, но вдруг пригодится статическая компиляция lua в паскаль
скалогрыз
долгожитель
 
Сообщения: 1803
Зарегистрирован: 03.09.2008 02:36:48

Re: Время жизни управляемых строк

Сообщение runewalsh » 15.05.2015 16:20:04

скалогрыз
>FPC won't accept borland of MSVC compiler object files
Так вот почему не получалось :D
Аватара пользователя
runewalsh
энтузиаст
 
Сообщения: 579
Зарегистрирован: 27.04.2010 00:15:25

Re: Время жизни управляемых строк

Сообщение скалогрыз » 15.05.2015 17:10:00

runewalsh писал(а):Так вот почему не получалось :D

mingw должен помочь! ты бы раньше спросил :)
скалогрыз
долгожитель
 
Сообщения: 1803
Зарегистрирован: 03.09.2008 02:36:48


Вернуться в Free Pascal Compiler

Кто сейчас на конференции

Сейчас этот форум просматривают: Yandex [Bot] и гости: 2

Рейтинг@Mail.ru