Проблема с TStringList при закрытии программы.
Модератор: Модераторы
Проблема с TStringList при закрытии программы.
Исходники примера: https://yadi.sk/d/0ZCHPRzCdqXuy
В архиве программа+dll к ней. В исходниках показан кусок моей программы, как она дает dll работать с своими командами. Все работает до момента обработки FormCloseQuery.
Суть следующая. Создается класс который предоставляет инструменты работы для библиотеки, и условно есть документ который программа обрабатывает. Если пользователь закрывает программу, то возникает FormCloseQuery. Если документ был закрыт до этого момента, то все хорошо, если документ открыт, то он закрывается и тут библиотека выполняет работу свою. Проблема в том, что когда угодно, До FormCloseQuery, после FormCloseQuery(если отмена закрытия была) доступен список TStringList, но если в момент выполнения FormCloseQuery пытаться с ним работать через dll, то финишь. Если без библиотеки, то все обрабатывается.
Как костыли прилепить я знаю, но вот может кто то скажет почему так?
В архиве программа+dll к ней. В исходниках показан кусок моей программы, как она дает dll работать с своими командами. Все работает до момента обработки FormCloseQuery.
Суть следующая. Создается класс который предоставляет инструменты работы для библиотеки, и условно есть документ который программа обрабатывает. Если пользователь закрывает программу, то возникает FormCloseQuery. Если документ был закрыт до этого момента, то все хорошо, если документ открыт, то он закрывается и тут библиотека выполняет работу свою. Проблема в том, что когда угодно, До FormCloseQuery, после FormCloseQuery(если отмена закрытия была) доступен список TStringList, но если в момент выполнения FormCloseQuery пытаться с ним работать через dll, то финишь. Если без библиотеки, то все обрабатывается.
Как костыли прилепить я знаю, но вот может кто то скажет почему так?
>>В архиве программа+dll к ней.
//ванга моде
не вижу общего менеджера памяти - 100% "очистка" строк в листе не менеджером в котором они выделены
>>Как костыли прилепить я знаю, но вот может кто то скажет почему так?
данный подход сам по себе костыль, такчто ненадо стесняться прилеплять))
update:
Имхо такой способ общения плагина и ексе годится только для построения настраиваемого в рантайме гуя и команд которые превносит в систему плагин, по хорошему общепринятые функции (команды) должны экспортироваться (просто export или передача какойнить структуры с адресами) ексешником и в длл пользоваться обычным способом
//ванга моде
не вижу общего менеджера памяти - 100% "очистка" строк в листе не менеджером в котором они выделены
>>Как костыли прилепить я знаю, но вот может кто то скажет почему так?
данный подход сам по себе костыль, такчто ненадо стесняться прилеплять))
update:
Код: Выделить всё
TAssiApp(Sender).Command('REFRESHINFOWINDOW');Имхо такой способ общения плагина и ексе годится только для построения настраиваемого в рантайме гуя и команд которые превносит в систему плагин, по хорошему общепринятые функции (команды) должны экспортироваться (просто export или передача какойнить структуры с адресами) ексешником и в длл пользоваться обычным способом
zub писал(а):не вижу общего менеджера памяти - 100% "очистка" строк в листе не менеджером в котором они выделены
Нахрена? При уничтожении объекта в его классе должно быть в любом случае обработана очистка памяти. Только TList не уничтожает свои ссылки.
Код: Выделить всё
Procedure TStringList.Clear;
begin
if FCount = 0 then Exit;
Changing;
[b]InternalClear;[/b]
Changed;
end;
destructor TStringList.Destroy;
begin
[b] InternalClear;[/b]
Inherited destroy;
end;
zub писал(а):Имхо такой способ общения плагина и ексе годится только для построения настраиваемого в рантайме гуя и команд которые превносит в систему плагин, по хорошему общепринятые функции (команды) должны экспортироваться (просто export или передача какойнить структуры с адресами) ексешником и в длл пользоваться обычным способом
Расскажи это создателям lisp и autocad. А вообще так и есть, подгружаемые в рантайме меню, команды из dll и команды с наборами параметров.
Нахрена? При уничтожении объекта в его классе должно быть в любом случае обработана очистка памяти. Только TList не уничтожает свои ссылки.
Теперь не ванга моде.
ошибка внутри fpc_ansistr_decr_ref
Как бы не выполнялась очистка, руками, по уничтожению владельца или еще как... говорит о том что куча сломана, т.е. скорее всего как я выше и говорил один менеджер пытается чистить за другим
Только TList не уничтожает свои ссылки.
незнаю какие ссылки ты имеешь ввиду, я имею ввиду уничтожение строк лежащих в списке, судя по всему какраз вот это:
Код: Выделить всё
[b]InternalClear;[/b]Создателям автокада мне сказать нечего, т.к. они не используют fpc в текущем его состоянии))
зы.
Я в пример особо не вникал, как я понял ошибка должна быть при закрытии окна программы и не должно быть если сначала нажать на кнопку. В моем транковом фпц ошибка присутствует в обоих случаях((
Теперь не ванга моде.
Так понятней.
Ну да, если типа "закрытие проекта" с вызовом dll через кнопку, а не по крестику формы и уже потом закрытие, то все нормально должно быть.
А какой версии fpc и lazarus у тебя?
А какой версии fpc и lazarus у тебя?
Вчерашние транковые и лазарь и фпц
В общем так, для закрытия темы.
Тот пример и правда не рабочий в ноль. Он будет таким как надо если использовать интерфейсы или абстрактный класс предок. Т.е. с глюком только при закрытии.
zub, спасибо за замечание про менеджер.
Сделал такое решение, чтобы развязать одну строку из dll на две:
Тот пример и правда не рабочий в ноль. Он будет таким как надо если использовать интерфейсы или абстрактный класс предок. Т.е. с глюком только при закрытии.
zub, спасибо за замечание про менеджер.
Сделал такое решение, чтобы развязать одну строку из dll на две:
Код: Выделить всё
function Command(ACommandStr: String; var OutResultIndex: Integer): boolean;
var
i,count,CharByte:integer;
IncomCommandStr: String;
begin
Result:=True;
IncomCommandStr:='';
Count:=Length(ACommandStr);
for i:=1 to Count do
begin
CharByte:=ord(ACommandStr[i]);
IncomCommandStr:=IncomCommandStr+char(CharByte);
end;
FCmdLast.Add(IncomCommandStr);
OutResultIndex:=1;
end;
Код: Выделить всё
IncomCommandStr:=IncomCommandStr+char(CharByte);Из за таких мест в программе производительность очень страдает. Длина известна, что мешает выделить выделить за один раз строку и скопировать?
Даже в таком виде будет в разы быстрее
Код: Выделить всё
begin
Result:=True;
Count:=Length(ACommandStr);
setlength(IncomCommandStr,Count);
for i:=1 to Count do
begin
IncomCommandStr[i]:=ACommandStr[i];
end;
FCmdLast.Add(IncomCommandStr);
OutResultIndex:=1;
end;Я все равно не догоняю упорство в неиспользовании cmem. И классы имхо нафиг не нужны, если уже разделять exe и dll - пока о них стоит забыть
