Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Базы данных и репортинг > AV при использовании компонентов DOA в нитях


Автор: icex 29.7.2008, 09:37
Добрый день.
Есть задача: Написать библиотеку (dll) доступа к БД Oracle, используя DOA.
Основное приложение загружает ее и работает через предоставленные интерфейсы.
Проблема: Возникают неуловимые (хаотичные) исключения типа AV в dll, при использовании в нитях (в каждой нити создается своя сессия для работы с БД).
У TOracleSession в dll свойство ThreadSafe = True.
Исключения возникают даже в случае простого соединения с БД (LogOn/LogOff)
Опытным путем было установлено, что исключения можно устранить, если в приложении и библиотеке включить использование runtime пакета rtl.
Но... в рамках поставленной задачи это не допустимо...
Может кто сталкивался, подскажите как лечить

Автор: icex 31.7.2008, 11:37
Добрый день, ЖК.
Разобрался, вообщем то DOA тут ни причем.
Проблема глубже и уходит в реализацию менеджера памяти :(

1. После долгих урезаний кода удалось локализовать проблему - в конструкторе TOracleSession создаются TThreadList'ы;
2. Начал копать дальше и вместо сессий создавать/уничтожать TThreadList - исключения остались.
Если смотреть код:

Код
constructor TThreadList.Create;
begin
  inherited Create;
  InitializeCriticalSection(FLock);
  FList := TList.Create;
  FDuplicates := dupIgnore;
end;

destructor TThreadList.Destroy;
begin
  LockList;    // Make sure nobody else is inside the list.
  try
    FList.Free;
    inherited Destroy;
  finally
    UnlockList;
    DeleteCriticalSection(FLock);
  end;
end;


видим что инициализируются критические секции и создается TList.

3. Скопировал реализацию классов (TList, TListEnumerator, TThreadList) в dll и отказался от модуля Classes - не помогло.
4. Закоментировал в конструкторе и деструкторе инициализацию критической секции - работает!
5. Раскоментировал и убрал создание TList - о чудо! и так работает. 
Шаманство...
6. После долгих танцев с бубном оказалось, что ошибок нет если убивать в том же порядке, в котором они создавалить...
Пришел к выводу: конфликтуют 2 менеджера памяти (один в основном приложении, другой в dll)...

Почему так? Скорее всего создатели Delphi не предполагали использования 2 менеджеров памяти в одном процессе

Автор: MetalFan 31.7.2008, 17:43
а зачем внутри TThreadList'а создавать еще один TList?

Автор: icex 1.8.2008, 09:13
Это борландовская реализация TThreadList

Автор: icex 4.8.2008, 09:07
В dll нужно установить глобальную константу: IsMultiThread := True

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)