Проблема с TStringList при закрытии программы.

Общие вопросы программирования, алгоритмы и т.п.

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

Проблема с TStringList при закрытии программы.

Сообщение Sharfik » 08.01.2015 09:01:57

Исходники примера: https://yadi.sk/d/0ZCHPRzCdqXuy

В архиве программа+dll к ней. В исходниках показан кусок моей программы, как она дает dll работать с своими командами. Все работает до момента обработки FormCloseQuery.
Суть следующая. Создается класс который предоставляет инструменты работы для библиотеки, и условно есть документ который программа обрабатывает. Если пользователь закрывает программу, то возникает FormCloseQuery. Если документ был закрыт до этого момента, то все хорошо, если документ открыт, то он закрывается и тут библиотека выполняет работу свою. Проблема в том, что когда угодно, До FormCloseQuery, после FormCloseQuery(если отмена закрытия была) доступен список TStringList, но если в момент выполнения FormCloseQuery пытаться с ним работать через dll, то финишь. Если без библиотеки, то все обрабатывается.
Как костыли прилепить я знаю, но вот может кто то скажет почему так?
Аватара пользователя
Sharfik
энтузиаст
 
Сообщения: 791
Зарегистрирован: 20.07.2013 01:04:30

Re: Проблема с TStringList при закрытии программы.

Сообщение zub » 08.01.2015 13:22:41

>>В архиве программа+dll к ней.
//ванга моде
не вижу общего менеджера памяти - 100% "очистка" строк в листе не менеджером в котором они выделены
>>Как костыли прилепить я знаю, но вот может кто то скажет почему так?
данный подход сам по себе костыль, такчто ненадо стесняться прилеплять))

update:
Код: Выделить всё
TAssiApp(Sender).Command('REFRESHINFOWINDOW');

Имхо такой способ общения плагина и ексе годится только для построения настраиваемого в рантайме гуя и команд которые превносит в систему плагин, по хорошему общепринятые функции (команды) должны экспортироваться (просто export или передача какойнить структуры с адресами) ексешником и в длл пользоваться обычным способом
zub
долгожитель
 
Сообщения: 2886
Зарегистрирован: 14.11.2005 23:51:26

Re: Проблема с TStringList при закрытии программы.

Сообщение Sharfik » 08.01.2015 21:18:21

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 и команды с наборами параметров.
Аватара пользователя
Sharfik
энтузиаст
 
Сообщения: 791
Зарегистрирован: 20.07.2013 01:04:30

Re: Проблема с TStringList при закрытии программы.

Сообщение zub » 08.01.2015 22:30:20

Нахрена? При уничтожении объекта в его классе должно быть в любом случае обработана очистка памяти. Только TList не уничтожает свои ссылки.

Теперь не ванга моде.
ошибка внутри fpc_ansistr_decr_ref
Как бы не выполнялась очистка, руками, по уничтожению владельца или еще как... говорит о том что куча сломана, т.е. скорее всего как я выше и говорил один менеджер пытается чистить за другим

Только TList не уничтожает свои ссылки.

незнаю какие ссылки ты имеешь ввиду, я имею ввиду уничтожение строк лежащих в списке, судя по всему какраз вот это:
Код: Выделить всё
[b]InternalClear;[/b]


Создателям автокада мне сказать нечего, т.к. они не используют fpc в текущем его состоянии))

зы.
Я в пример особо не вникал, как я понял ошибка должна быть при закрытии окна программы и не должно быть если сначала нажать на кнопку. В моем транковом фпц ошибка присутствует в обоих случаях((
zub
долгожитель
 
Сообщения: 2886
Зарегистрирован: 14.11.2005 23:51:26

Re: Проблема с TStringList при закрытии программы.

Сообщение Sharfik » 08.01.2015 23:08:41

Теперь не ванга моде.

Так понятней.

Ну да, если типа "закрытие проекта" с вызовом dll через кнопку, а не по крестику формы и уже потом закрытие, то все нормально должно быть.
А какой версии fpc и lazarus у тебя?
Аватара пользователя
Sharfik
энтузиаст
 
Сообщения: 791
Зарегистрирован: 20.07.2013 01:04:30

Re: Проблема с TStringList при закрытии программы.

Сообщение zub » 08.01.2015 23:48:09

А какой версии fpc и lazarus у тебя?

Вчерашние транковые и лазарь и фпц
zub
долгожитель
 
Сообщения: 2886
Зарегистрирован: 14.11.2005 23:51:26

Re: Проблема с TStringList при закрытии программы.

Сообщение Sharfik » 11.01.2015 02:49:52

В общем так, для закрытия темы.
Тот пример и правда не рабочий в ноль. Он будет таким как надо если использовать интерфейсы или абстрактный класс предок. Т.е. с глюком только при закрытии.
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;
Аватара пользователя
Sharfik
энтузиаст
 
Сообщения: 791
Зарегистрирован: 20.07.2013 01:04:30

Re: Проблема с TStringList при закрытии программы.

Сообщение zub » 11.01.2015 17:22:56

Код: Выделить всё
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 - пока о них стоит забыть
zub
долгожитель
 
Сообщения: 2886
Зарегистрирован: 14.11.2005 23:51:26


Вернуться в Общее

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

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 17

Рейтинг@Mail.ru