Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 21.11.2015, 09:37   #1
lollollollol
Форумчанин
 
Регистрация: 23.03.2013
Сообщений: 218
По умолчанию

Моя длл подгружается в мой exe.

Вызывается функция дллки, которая использует синапс для подключения к сайту.
Когда софт работает в один поток, проблем нет!
Но стоит запустить хотябы 2 потока, вылетает с ошибкой памяти (access violation и некоторые другие, ошибка чтения/записи, всегда поразному).
Примечательно то, что после первого вылета с ошибкой больше функция не выполняется вообще. Как будь-то в памяти дллки всё нарушилось, и нет больше вызываемой функции.

так вот код дллки:

Код:
//КОД
HTTP.HTTPMethod('POST',URL);
//КОД
Вот если сделать так:

Код:
//КОД
HTTP.HTTPMethod('POST',URL);
HTTP.Free;
result:=1;
exit;
То я получаю ошибку.
А если сделать так:

Код:
HTTP.Free;
result:=1;
exit;
HTTP.HTTPMethod('POST',URL);
//КОД
Ошибки нет!

Вывод - проблема в HTTP.HTTPMethod.

Я бы подумал может какая проблема в синхронизации, но если прямо в длл вызвать этот код, даже в 100 потоков всё реботает идеально.
Проблема только тогда, когда вызываю функцию из загруженой дллки.

Добавлю что директива stdcall; установлена в описании функции в длл и в описании функции вызова.


Кто может подсказать как побороть проблему?
Вариант переместить код в проект ехе и отказаться о длл не устраивает, ибо совсем каша кода получится. Да и для дальнейшего развития проекта длл удобнее.

Заранее спасибо

А ещё вопрос, когда 2 потока вызывают одну функцию в длл, на каждую функцию создаётся свой поток? или как?

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

И что правильнее использовать,
hThread:=BeginThread(nil,0,@THREAD_ START,nil,0,ThID);


или

hThread:=CreateThread(nil,0,@THREAD _START,nil,0,ThID);


я разницы не увидел

Последний раз редактировалось Stilet; 21.11.2015 в 09:53.
lollollollol вне форума Ответить с цитированием
Старый 21.11.2015, 10:00   #2
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

Цитата:
Вот если сделать так:
Полностью код этой функции в студию.
Цитата:
А если сделать так:
А если почитать книжки по паскалю? Не? Не поможет? Особенно про оператор exit.
Цитата:
когда 2 потока вызывают одну функцию в длл, на каждую функцию создаётся свой поток? или как?
Нет. Не поток. Функция просто вызывается в сегменте стека потока храня переданные ей параметры и локальные переменные. Но никакой поток при этом не создается. Говорят "Функция работает в контексте потока".
Цитата:
просто мжет есть смысл функцией создавать поток, ждать его завершения, и возвращать ответ... хотя мне кажется изврат конкретный. не должно так быть
Почему изврат? Я так и делаю. Понадобилось чет слямзить из инета - создается поток, в него передаются параметры, поток отрабатывает и тю-тю.
Если делать это функцией то можно callback применить:
Код:
TFunc=procedure(s:string);
...
function DoThre(url:String;CallBack:TFunc):Boolean;
Т.е. вызвать функу, передать ей Урл и указатель на обработчик, что сам поток вызовет после закачки данных.
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 21.11.2015, 10:14   #3
lollollollol
Форумчанин
 
Регистрация: 23.03.2013
Сообщений: 218
По умолчанию

Цитата:
А если почитать книжки по паскалю? Не? Не поможет? Особенно про оператор exit.
Я специально так сделал, показать, что проблема именно в строке запроса синапса.


остальной код не имеет значения в данном случае. Т.к. всё работает стабильно если длл запустить как ехе и прямо из неё выполнять код.

Сейчас попробую через поток, посмотрим что получится.



Я думал что функуия дллки выполняется в потоке, который её вызвал! или нет?
Если так, проблем быть не должно.
А если я создаю поток уже прямо в длл, получается что на одну функциюбудет создано аж 2 потока.
Поясню, что я именно в потоке вызываю функцию дллки!

Последний раз редактировалось lollollollol; 21.11.2015 в 10:16.
lollollollol вне форума Ответить с цитированием
Старый 21.11.2015, 10:20   #4
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

Цитата:
Я думал что функуия дллки выполняется в потоке, который её вызвал! или нет?
Ну правильно.
Цитата:
если я создаю поток уже прямо в длл, получается что на одну функциюбудет создано аж 2 потока.
Я почему код в студию прошу - чтоб понять что ты там такое создаешь. Я без понятия как у тебя там вложенность сделана, по твоим описаниям это понять сложно.
Цитата:
я именно в потоке вызываю функцию дллки!
Тем более код в студию.
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 21.11.2015, 10:37   #5
lollollollol
Форумчанин
 
Регистрация: 23.03.2013
Сообщений: 218
По умолчанию

Код:
 
//Загружаю длл
var
  Get_Info   : function (info:Tinfo;Account:AnsiString;var inbox:Tinbox;IdGetMess:AnsiString):integer; stdcall;
  Send_Info  : function (info:Tinfo;Account:AnsiString; var unread:Tunread):integer; stdcall;

...

DLL:=ExtractFilePath(ParamStr(0))+'INFO.dll';
  if (FileExists(DLL)=true) then begin
    h:=LoadLibraryA(PAnsiChar(DLL));
    if (h<>0) then begin
      @Get_Info     := GetProcAddress(h, 'Get_Info');
      @Send_Info    := GetProcAddress(h, 'Send_Info');
    end else begin
      MessageBox(0,Pchar(inttostr(GetLastError)),'GetLastError',0);
      Application.Terminate;
    end;
  end else begin
    MessageBoxA(0,PANsichar('Error dll'+#13#10#13#10+DLL),'ERROR',0);
    Application.Terminate;
  end;     

...

  //Запуск потоков рассылки
n:=3;
  a:=0;
  while (a<n) do begin
    hThread:=BeginThread(nil,0,@THREAD_WORK,nil,0,ThID);
    CloseHandle(hThread);
    inc(a);
  end;

...

//Поток
procedure THREAD_WORK; stdcall;
...
SendResult := Send_Info(Info,acc,unread);

и в дллке

Код:
function Send_Info(info:Tinfo;Account:AnsiString; var unread:Tunread):integer; stdcall;
var
...
begin
...
//Вот если остановить выполнение функции тут, то ошибки нет
    HTTP.HTTPMethod('POST',URL);
//Если установить выполнение функции тут, то в случае ДВУХ И БОЛЕЕ потоков вылетает ошибка памяти. 
После первой ошибки, при повторных попытках вызова функции, функция не выполняясь сразу заканчивается ошибкой. 
даже первая строка не выполняется.
...
Вот инфа об ошибке
Цитата:
Имя события проблемы: APPCRASH
Имя приложения: Project1.exe
Версия приложения: 0.0.0.0
Отметка времени приложения: 56503609
Имя модуля с ошибкой: INFO.dll

Добавлю, что если я скомпилирую вместо дллки проект как exe, и создам потоки прямо в этом файле, то данная функция работает без проблем даже в 100 потоков! Даже через час жесткой работы в дипетчерез задач видно, что нет утечки памяти.

Последний раз редактировалось Stilet; 21.11.2015 в 10:59.
lollollollol вне форума Ответить с цитированием
Старый 21.11.2015, 10:49   #6
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
По умолчанию

HTTP часом не глобальный объект?
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.
Пепел Феникса вне форума Ответить с цитированием
Старый 21.11.2015, 10:53   #7
lollollollol
Форумчанин
 
Регистрация: 23.03.2013
Сообщений: 218
По умолчанию

нет конечно!
В дллке вообще нет глобальных переменных.

Да и еслиб он был глобальным, не работали бы 100 потоков при запуске в процессе.

проблема имено с вызовом функции из длл, ну или в чём там ещё... не пойму в чём проблема.

проблема возникает именно когда 2 потока ОДНОВРЕМЕННО начинают загружать информацию. Если по очереди тоже проходит гладко всё.
Может как-то с переполнением памяти связано. Дллкаже ограничена в памяти моего поцесса...

Последний раз редактировалось Stilet; 21.11.2015 в 11:33.
lollollollol вне форума Ответить с цитированием
Старый 21.11.2015, 11:00   #8
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

Мдя... Самое главное ты и не показал...
Ладно, скажу напоследок: HTTP создавай и освобождай в пределах функции, и переменка эта должна быть локальной.
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 21.11.2015, 11:05   #9
lollollollol
Форумчанин
 
Регистрация: 23.03.2013
Сообщений: 218
По умолчанию

ёмаё, вот то что ты сказал впринципе не обсуждается, это так и сделано.

А не показал я это потому, что даже подумать не мог, что как-то иначе можно сделать
lollollollol вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Проблема с dll Кольша Общие вопросы Delphi 21 22.12.2013 20:33
Проблема dll EXMP Софт 0 18.08.2010 09:30
Dll - проблема nXs Общие вопросы Delphi 2 16.07.2010 14:53
Проблема с DLL _-Re@l-_ Паскаль, Turbo Pascal, PascalABC.NET 3 09.06.2010 14:28
Проблема с dll( DM_bite Помощь студентам 10 31.07.2008 16:05