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

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
Ошибка при работе с потоками в DLL
    #40069304
Соколинский Борис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
HOME_X,
cкорее всего обычная заморочка с со скрытыми ссылками.
Если библиотеке есть функции, возвращающие интерфейсы, оберни их вызов в процедуры с out-параметрами.
...
Рейтинг: 0 / 0
Ошибка при работе с потоками в DLL
    #40069310
HOME_X
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Соколинский Борис
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
Ошибка при работе с потоками в DLL
    #40069313
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
HOME_XpFile:=PAnsiChar(AnsiString(aFile));

А вот за такое отрывают руки. Хотя вменяемые компиляторы сами ругаются о получении
указателя на временный объект. К моменту вызова Create_AddSpan этот указатель уже
становится инвалидным и указывает на мусор.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Ошибка при работе с потоками в DLL
    #40069315
HOME_X
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
[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
Ошибка при работе с потоками в DLL
    #40069318
HOME_X
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry Sibiryakov

HOME_XpFile:=PAnsiChar(AnsiString(aFile));

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



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

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

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

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

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


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

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

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

И зачем вы указатели ещё в OleVarian оборачиваете?
...
Рейтинг: 0 / 0
Ошибка при работе с потоками в DLL
    #40069325
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Почитать теорию о времени жизни переменных и работе с памятью.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Ошибка при работе с потоками в DLL
    #40069327
HOME_X
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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
Ошибка при работе с потоками в DLL
    #40069330
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
HOME_X
исполняемый модуль 64 bit
HOME_X
Код: pascal
1.
ovMes:=OleVariant(Integer(sbMain));

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

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


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

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


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

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

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

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


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

Нет, не вся. Только та, что выделилась при загрузке. И та, которую код этой DLL соизволит
освободить при выгрузке. Что, впрочем, у стандартного дельфийского менеджера - вся его
куча. Но у ТС-а и с локальными переменными-то беда, не то что с возвратом.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Ошибка при работе с потоками в DLL
    #40069491
HOME_X
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_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
Ошибка при работе с потоками в DLL
    #40069497
HOME_X
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry Sibiryakov

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

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


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

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

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

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

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

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

Но вот быстрый способ:
Код: 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
Ошибка при работе с потоками в DLL
    #40069551
HOME_X
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
GunSmoker

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


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

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

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

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

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


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