Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Ошибка при работе с потоками в DLL / 25 сообщений из 33, страница 1 из 2
11.05.2021, 12:21
    #40069302
HOME_X
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка при работе с потоками в DLL
Доброго дня господа !

Delphi 10.3.3 64xbit

Имею архитектуру
- исполняемый модуль 64 bit в нем TStatusBar с набором панелей.
- модуль библиотеки DLL 64 bit здесь в потоке выполняется запрос
и сообщения о статусе выполнения работ передается в основную форму
TStatusBar.Panels[1].Text:='Work/Closed и т.д.'

В момент закрытие библиотеки DLL после выполнения всего процесса
FreeLibrary(LibHandle);

Наблюдаю потерю указателе ИЛИ обнуливание семейства Panels

кодом это выглядит так
Запуск


Код: pascal
1.
2.
3.
4.
5.
6.
  // sbMain : TStatusBar;

  ovMes:=OleVariant(Integer(sbMain));
  LibHandle:=LoadLibrary('MyLibrary.dll');
  if(LibHandle      >= 32)then @Create_AddSpan:=GetProcAddress(LibHandle,'Create_AddSpan');
  if(@Create_AddSpan<>nil)then Thread:=Create_AddSpan(pFile,pList,aKind,ovBar,ovMes,frMain.Handle,ovSql,ovRecordSet);




Завершение потока по событию - передача события в основную форму
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
procedure TfrMain.WmExitThread(var Msg: TMessage);
vegin
  if(Msg.Msg=Wm_ExitThread) then begin
   if(Msg.LParam<>0)then FreeAndNil(TObject(Msg.LParam));
    if(Thread<>0)    then CloseHandle(Thread);
    ShowMessage(IntToStr(sbMain.Panels.Count));  // здесь семейство еще есть
    ShowMessage('1 0 '+sbMain.Panels[0].Text);
    if(LibHandle>=32)then FreeLibrary(LibHandle);
    ShowMessage(IntToStr(sbMain.Panels.Count)); // здесь семейство уже уничтожено или потерян указатель
    ShowMessage('2 0 '+sbMain.Panels[0].Text);



Ошибку наблюдаю в момент закрытия основного окна - когда идет destroy все обьектов

Вот такая ситуация - помогите если сталкивались

P. S . - если в DLL не передавать параметр на визуализацию статусов ovMes
if(@Create_AddSpan<>nil)then Thread:=Create_AddSpan(pFile,pList,aKind,ovBar, ovMes ,frMain.Handle,ovSql,ovRecordSet);

Ошибки не происходит
Спасибо
...
Рейтинг: 0 / 0
11.05.2021, 12:29
    #40069304
Соколинский Борис
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка при работе с потоками в DLL
HOME_X,
cкорее всего обычная заморочка с со скрытыми ссылками.
Если библиотеке есть функции, возвращающие интерфейсы, оберни их вызов в процедуры с out-параметрами.
...
Рейтинг: 0 / 0
11.05.2021, 12:38
    #40069310
HOME_X
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка при работе с потоками в DLL
Соколинский Борис
HOME_X,
cкорее всего обычная заморочка с со скрытыми ссылками.
Если библиотеке есть функции, возвращающие интерфейсы, оберни их вызов в процедуры с out-параметрами.


Это простой набор OveVariant параметров

Библиотека
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
  function Create_AddSpan(aFile: PAnsiChar; aList: PAnsiChar; aKind: OleVariant; aBars: OleVariant; aMess: OleVariant; aHandle: OleVariant; var aSql: OleVariant; var aRecordSet: OleVariant): Integer;
  var
    S: String;
    B: TProgressBar;
    M: TStatusBar;
    Id: Cardinal;
    H:  THandle;
  begin
    Result:=1;
    if (aBars  <>Null)then B:=TProgressBar(Integer(aBars)) else B:=Nil;
    if (aMess  <>Null)then M:=TStatusBar(Integer(aMess))   else M:=Nil;
    if (aHandle<>Null)then H:=THandle(Integer(aHandle))    else H:=0;
    A:=TAddSpan.Create(iif((Integer(aKind)=0)or(Integer(aKind)=3),'[Path]'+vbLine+String(aList),String(aFile)),B,M,H,aSql,aRecordSet);
    if (A.Kind=0) then A.ExecuteItem;
    if (A.Kind=1) then A.ExecuteLoop;
    if (A.Kind=2) or (A.Kind=3) then Result:=BeginThread(Nil,0,@MainThread,A,0,Id);
    if (A.Kind=0) or (A.Kind=1) then FreeAndNil(A);
  end;



Вызов из основного окна
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
  public
    Thread:    Integer;
    LibHandle: THandle;
    ovBar,ovMes,ovHandle,ovSql,ovRecordSet: OleVariant;
    Create_AddSpan: function(aFile: PAnsiChar; aList: PAnsiChar; aKind: OleVariant; aBars: OleVariant; aMess: OleVariant; aHandle: OleVariant; var aSql: OleVariant; var aRecordSet: OleVariant): Integer; stdcall;


procedure TfrMain.ExecuteQuery(aFile: String; aList: String; aKind: Integer);
var
    pFile,pList: PAnsiChar;
begin
  Thread        :=0;
  LibHandle     :=0;
  if(ParamStr(6)='Bar')then ovBar:=OleVariant(Integer(pbMain)) else ovBar:=Null;
  if(ParamStr(6)='Bar')then ovMes:=OleVariant(Integer(sbMain)) else ovMes:=Null;
  ovHandle      :=Null;
  ovSql         :=Null;
  ovRecordSet   :=Null;
  Create_AddSpan:=Nil;
  pFile:=PAnsiChar(AnsiString(aFile));
  pList:=PAnsiChar(AnsiString(aList));
  LibHandle:=LoadLibrary('MyLibrary.dll');
  if(LibHandle      >= 32)then @Create_AddSpan:=GetProcAddress(LibHandle,'Create_AddSpan');
  if(@Create_AddSpan<>nil)then Thread:=Create_AddSpan(pFile,pList,aKind,ovBar,ovMes,frMain.Handle,ovSql,ovRecordSet);
end;



Не могли бы уточнить на примере - как реализовать
Спасибо
...
Рейтинг: 0 / 0
11.05.2021, 12:41
    #40069313
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка при работе с потоками в DLL
HOME_XpFile:=PAnsiChar(AnsiString(aFile));

А вот за такое отрывают руки. Хотя вменяемые компиляторы сами ругаются о получении
указателя на временный объект. К моменту вызова Create_AddSpan этот указатель уже
становится инвалидным и указывает на мусор.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
11.05.2021, 12:45
    #40069315
HOME_X
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка при работе с потоками в DLL
[quot HOME_X#22320390]
Соколинский Борис


function Create_AddSpan(aFile: PAnsiChar; aList: PAnsiChar; aKind: OleVariant; aBars: OleVariant; VAR aMess: OleVariant; aHandle: OleVariant; var aSql: OleVariant; var aRecordSet: OleVariant): Integer;

Типа так ?
...
Рейтинг: 0 / 0
11.05.2021, 12:49
    #40069318
HOME_X
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка при работе с потоками в DLL
Dimitry Sibiryakov

HOME_XpFile:=PAnsiChar(AnsiString(aFile));

А вот за такое отрывают руки. Хотя вменяемые компиляторы сами ругаются о получении
указателя на временный объект. К моменту вызова Create_AddSpan этот указатель уже
становится инвалидным и указывает на мусор.



Работает - нормально и долго !!!!
Предлагаете реализовать через поле объекта ?
Нет вопросов - учту - спасибо
...
Рейтинг: 0 / 0
11.05.2021, 12:50
    #40069320
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка при работе с потоками в DLL
HOME_XРаботает - нормально и долго !!!!

"Дуракам везёт."

Я предлагаю передавать в функцию валидный указатель и прочитать теорию о времени жизни
переменных.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
11.05.2021, 12:57
    #40069322
HOME_X
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка при работе с потоками в DLL
Dimitry Sibiryakov

HOME_XРаботает - нормально и долго !!!!

"Дуракам везёт."


Если бы на деньги ...

А по сути темы, что - то подскажите ?
Как устранить ошибку с указателями ?
...
Рейтинг: 0 / 0
11.05.2021, 13:02
    #40069324
zedxxx
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка при работе с потоками в DLL
Код: pascal
1.
Integer(sbMain)

- для 64-х битных указателей так делать нельзя. Используйте для этого UIntPtr http://docwiki.embarcadero.com/Libraries/Sydney/en/System.UIntPtr

И зачем вы указатели ещё в OleVarian оборачиваете?
...
Рейтинг: 0 / 0
11.05.2021, 13:03
    #40069325
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка при работе с потоками в DLL
Почитать теорию о времени жизни переменных и работе с памятью.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
11.05.2021, 13:08
    #40069327
HOME_X
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка при работе с потоками в DLL
zedxxx
Код: pascal
1.
Integer(sbMain)

- для 64-х битных указателей так делать нельзя. Используйте для этого UIntPtr http://docwiki.embarcadero.com/Libraries/Sydney/en/System.UIntPtr

И зачем вы указатели ещё в OleVarian оборачиваете?



"..64-х битных указателей.."
Принято - это был переход с 32- bit версии !

"..OleVariant .."
DLL - используется НЕ ТОЛЬКО Delphi а еще из VBA и COM- серверами системы
...
Рейтинг: 0 / 0
11.05.2021, 13:18
    #40069330
_Vasilisk_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка при работе с потоками в DLL
HOME_X
исполняемый модуль 64 bit
HOME_X
Код: pascal
1.
ovMes:=OleVariant(Integer(sbMain));

Дальше можно не смотреть
...
Рейтинг: 0 / 0
11.05.2021, 13:31
    #40069332
Гаджимурадов Рустам
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка при работе с потоками в DLL
HOME_X,

Модератор: Аккуратнее с названиями топиков и лексикой, пожалуйста.
...
Рейтинг: 0 / 0
11.05.2021, 13:39
    #40069333
white_nigger
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка при работе с потоками в DLL
_Vasilisk_
HOME_X
исполняемый модуль 64 bit
HOME_X
Код: pascal
1.
ovMes:=OleVariant(Integer(sbMain));


Дальше можно не смотреть
Да там вообще лютый треш
...
Рейтинг: 0 / 0
11.05.2021, 15:29
    #40069368
cptngrb
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка при работе с потоками в DLL
Dimitry Sibiryakov

Почитать теорию о времени жизни переменных и работе с памятью.


а где такое расписано для двоечников?
...
Рейтинг: 0 / 0
11.05.2021, 15:38
    #40069372
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка при работе с потоками в DLL
cptngrbа где такое расписано для двоечников?

В букваре?..
https://learndelphi.org/resources/программирование-на-delphi-для-школ/
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
11.05.2021, 16:37
    #40069389
cptngrb
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка при работе с потоками в DLL
Dimitry Sibiryakov,
там такого не пишут.
вот тут немножко https://www.rsdn.org/article/Delphi/memmanager.xml
...
Рейтинг: 0 / 0
11.05.2021, 17:58
    #40069408
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка при работе с потоками в DLL
cptngrbтам такого не пишут.

А зря.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
11.05.2021, 18:01
    #40069409
GunSmoker
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка при работе с потоками в DLL
Букварь о разработке своей DLL для двоечников.

По сути вопроса - при выгрузке DLL освобождается вся её память. Соответственно, если вы из DLL выделили память (читай: объекты, интерфейсы и т.п.) и передали куда-то, то этой памяти будет капут.
...
Рейтинг: 0 / 0
11.05.2021, 18:05
    #40069410
cptngrb
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка при работе с потоками в DLL


Давно читал эту классную статью. В своих проектах очень много используется PAnsiChar и все что с ним связано, после прочтения WideString ))
...
Рейтинг: 0 / 0
11.05.2021, 18:07
    #40069412
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка при работе с потоками в DLL
GunSmokerпри выгрузке DLL освобождается вся её память.

Нет, не вся. Только та, что выделилась при загрузке. И та, которую код этой DLL соизволит
освободить при выгрузке. Что, впрочем, у стандартного дельфийского менеджера - вся его
куча. Но у ТС-а и с локальными переменными-то беда, не то что с возвратом.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
11.05.2021, 23:55
    #40069491
HOME_X
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка при работе с потоками в DLL
_Vasilisk_
HOME_X
исполняемый модуль 64 bit
HOME_X
Код: pascal
1.
ovMes:=OleVariant(Integer(sbMain));

Дальше можно не смотреть



ovMes:=OleVariant(Integer(sbMain));

Мне необходимо вызывать функцию DLL из под MS Office и Delphi,
других совместимых и работающих типов не нашел (в свое время искал и пробывал)
Это " Р А Б О Т А Е Т !!! " (может "дуракам везет" - смотри замечание выше)

Если подскажите как совместить - уточню задачу четко и конкретно !

P.S. Насчет Integer - согласен остатки 32 bit версии
...
Рейтинг: 0 / 0
12.05.2021, 00:19
    #40069497
HOME_X
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка при работе с потоками в DLL
Dimitry Sibiryakov

GunSmokerпри выгрузке DLL освобождается вся её память.

Нет, не вся. Только та, что выделилась при загрузке. И та, которую код этой DLL соизволит
освободить при выгрузке. Что, впрочем, у стандартного дельфийского менеджера - вся его
куча. Но у ТС-а и с локальными переменными-то беда, не то что с возвратом.


Насчет памяти, которая была выделена в момент загрузке вопрос абсолютно ясен

Как понять "DLL соизволил" ?
Передаваемая память принадлежит другому процессу
Она создана другим процессом и инициализирована другим процессом.
и явной команды на удаление этой памяти нет.

Суть в том, что на данной DLL и на данной схеме подключения у меня работает на менее 15-20
приложений и вопросов не возникало. (от слова совсем)

Замечу, что по такой же схеме реализован код
if (aBars <>Null)then B:=TProgressBar(Integer(aBars)) else B:=Nil;
Это прогресс бар на моменты импорта данных из запроса
Все абсолютно идентично. передача данных , изменение их состояния....
Тема "дуракам везет слишком часто" в большой статистике не прокатывает.
Возможно я что-то упустил, например моменты потоковой и "сплошной" инициализации данных ?

Как выйти из положения имея в основе выше указанный код, приведите пример пожалуйста.

Благодарен за Ваше участие и обсуждение
...
Рейтинг: 0 / 0
12.05.2021, 09:03
    #40069529
GunSmoker
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка при работе с потоками в DLL
У вас настолько лютый треш написан, что никто в это говно (уж извините) погружаться не хочет. Тем более, что много важных деталей вы не упоминаете вообще, видимо, не понимая их важности. А клещами тащить их из вас, да ещё и объяснять что к чему...

Но вот быстрый способ:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
type
  TStatusPanel = class(ComCtrls.TStatusPanel)
  public
    destructor Destroy; override;
  end;

  TStatusBar = class(ComCtrls.TStatusBar)
  protected
    function GetPanelClass: TStatusPanelClass; override;
  public
    destructor Destroy; override;
  end;

  TfrMain= class(TForm)
    // ...
  end;

// ...

destructor TStatusPanel.Destroy;
begin
  inherited; // - бряк ставится здесь
end;

function TStatusBar.GetPanelClass: TStatusPanelClass;
begin
  Result := TStatusPanel;
end;

destructor TStatusBar.Destroy;
begin
  inherited; // - бряк ставится здесь
end;



Ну, типа, запускаете приложение, выходите, и смотрите в какой момент срабатывает бряк. По Call Stack смотрите кто и откуда его дёргает.

Если проблема не в этом, то - ой. Значит, всё же проблема с памятью. Тогда надо весь код пересматривать/переделывать.
...
Рейтинг: 0 / 0
12.05.2021, 10:29
    #40069551
HOME_X
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка при работе с потоками в DLL
GunSmoker

Значит, всё же проблема с памятью.


Это проблема с памятью вызванная FreeLibrary(LibHandle)
Ссылок на TStatusBar в основном потоке нет
(сейчас еще проведу пару тестов)

Как бы Вы решили данную задачу
основной поток - здесь TProgressBar и TStatusBar
DLL библиотека - здесь создается объект и один из его методов работает в потоке, где организован цикл по TQuery
(или просто цикл) и вывод промежуточных результатов выполнения на вышеупом-е объекты

Передача параметров в DLL типах OleVariant
(DLL используется НЕ ТОЛЬКО Delphi)

Буду весьма признателен за пример в коде

Спасибо за общение
...
Рейтинг: 0 / 0
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Ошибка при работе с потоками в DLL / 25 сообщений из 33, страница 1 из 2
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]