-
Игорь Шевченко © (25.04.08 19:05) [59] потоки не создаются в DLL. Потоки создаются в процессе
а вам доставляет удовольствие цепляться к словам? Любопытно посто.
Если действительно непонятна фраза "потоки созданные в DLL" - я уточню. Это потоки, которые созданы в том месте маш. кода, который был загружен в ВАП процесса при проецировании образа DLL.
К чему еще изволите придраться?
-
Пробегал2... (25.04.08 19:18) [60]
И чем они отличаются от потоков, созданных в другом месте кода ?
-
> Пробегал2... (25.04.08 19:18) [60]
> Это потоки, которые созданы в том месте маш. кода, который > был загружен в ВАП процесса при проецировании образа DLL
Не нало месить кислое и фиолетовое.
-
Игорь Шевченко © (25.04.08 19:23) [61] И чем они отличаются от потоков, созданных в другом месте кода ?
тем, что потоки созданные в DLL должны уничтожаться также в DLL. Это логичная методика работы.
DLL как черный ящик, она экспортирует нужный мне функционал, а как она его реализовывает - мне все равно. И то что создано в DLL - внутри нее же и должно быть финализировано.
С таким же успехом и глобальные переменные, выделенные в DLL - можно очищать в самом приложении, не так ли? Только это нелогично, это - неудобно.
Плюс весь WinApi спроектирован таким образом и я думаю стоит придерживаться этого подхода. Когда вам требуется принять некую структуру данных - ВЫ выделяете память под нее и передаете на нее ссылку, по которой эта структура заполняется библиотекой. Заметьте, не библиотека выделяет память и передает ссылку на заполненную структуру, которую ВЫ потом должны уничтожить. Принцип один: если намусорил - подчисти за СОБОЙ.
И если там какая-то DLL создала поток для реализации функционала - она же этот поток и должна уничтожить. Имхо, если DLL хорошо спроектирована - то я в любое время могу вызывать FreeLibrary - и DLL должна очистить все ресурсы, занятые ею в процессе работы и вернуть все в то состояние, которое было до вызова LoadLibrary.
-
Пробегал2... (25.04.08 20:35) [63]
Это всего лишь твое имхо. Ни больше, ни меньше. В системе и в приложениях есть примеры и одного подхода, и другого, не надо выдавать свое имхо за абсолютную истину, а главное, делать из этого имха какие-то глобальные выводы.
-
Удалено модератором
-
Здесь http://msdn2.microsoft.com/en-us/library/ms885202.aspxчерным по белому нарисована логика вызовов DllMain с тем или иным резоном. С учетом же того, что вызовы DllMain конкретного модуля в контексте текущего процесса осуществляются системой синхронно, "феномен зависания" становится совершенно очевидным и понятным, даже без вникания во всякие там PEBы и TIBы.
-
))
-
> ну нифига... У тебя все расчитано, что максимум будет создан > один поток.. Второй поток уже внесет несусветную суматоху.
мне просто не требуется, чтобы в программе крутилось несколько однотипных потоков, поэтому выбрано такое решение. В других случаях будет выбрано другое решение. Кстати, после WaitForSingleObject() стоило бы выждать хотябы немного времени (например 50 / 100 мс), чтобы стать более уверенным, что функция потока уперлась в ExitThread() (а этот код уже выполняется не в нашей DLL-ке, а в kernel) и ожидает снятия блокировки, в этом случае выгрузка библиотеки уже точно ни на что не повлияет, и никаких AV не будет.
> да с чего ты взял, что винда потоки срубает?!?! Винда финализирует > потоки не при FreeLibrary
Вот срубает и все тут. Причем FreeLibrary() перед закрытием программы вызывается. В одном случае срубает, в другом - не срубает. Есть конечно подозрение, что где-то в системе лишний раз LoadLibrary() для моей библиотеки кто-то вызвал, но наврядли... Проверю на следующей неделе.
> И чем они отличаются от потоков, созданных в другом месте > кода ?
Потоковой функцией, код которой выгружается вместе с DLL-кой в том случае, если он принадлежит DLL-ке.
-
Игорь Шевченко © (25.04.08 20:42) [64] Это всего лишь твое имхо. Ни больше, ни меньше
ок, давайте по другому. Игорь, только честно - у вас были проекты, где поток создавался в коде DLL, а завершался в другом месте?
P.S. Это я уже не говорю об использовании класса TThread, там уж как ни крути финализировать надо там же, где создаешь.
-
Пробегал2... (25.04.08 21:42) [69]
Я не единственный разработчик программного обеспечения на этом свете. И на слабо бери кого-нибудь другого.
-
Игорь Шевченко © (25.04.08 22:50) [70]
как я понимаю, ответ нет, ни в одном проекте вы так не делали. Что и требовалось доказать.
-
Пробегал2... (25.04.08 23:40) [71]
И на слабо бери кого-нибудь другого. Доказатель фигов
-
ну хорошо. Я моих проектах никогда не было, чтобы поток создавался в DLL, а завершался в другой DLL или в самом приложении. И мне такой подход кажется нелогичным и путанным, когда DLL обязывает выполнять какие-то телодвижения кроме загрузки и выгрузки библиотеки.
Да, это мое ИМХО. ну не согласны - и не согласны ;)
-
Пробегал2... (26.04.08 02:52) [73]
С точки зрения процесса, и основное приложения и DLL - это всего лишь части кода, связанные в единое адресное пространство (про различные менеджеры памяти или VMT для дельфийских классов в этом аксепте упоминать сейчас не будем, так как консепция потоков не зависит от используемого языка программирования). Таким образом, ничто не мешает потоку, начавшись в одной части кода. завершится абсолютно в другой. Система это делать позволяет. Более того, система даже позволяет создать поток в одном приложении, а завершать его в другом, используя функции CreateRemoteThread и TerminateThread
Давайте все-таки различать - возможно/невозможно и удобно/неудобно
-
Игорь, я Вами восхищаюсь :)
-
Удалено модератором
-
Кто-нибудь может привести пример(свой, чужой - неважно), где бы в DLL создавался поток (BeginThread/TThread), затем DLL из приложения выгружалась бы, а поток продолжал работать?
-
> где бы в DLL создавался поток (BeginThread/TThread), затем > DLL из приложения выгружалась бы, а поток продолжал работать?
На ум приходит только одно: потоковая функция расположена в другом модуле.
-
> > где бы в DLL создавался поток (BeginThread/TThread), затем > > DLL из приложения выгружалась бы, а поток продолжал работать? > На ум приходит только одно: потоковая функция расположена > в другом модуле.
Потоковая это только адрес начала потока, далее может быть переходы куда угодно. Легко представить себе начало потока в dll, затем продолжение в другой и вызов ExitThread уже оттуда. Можно даже и без ExitThread, обычным возвратом, просто переход в другой модуль не по call, а по jmp. Или так: в потоке создаются фиберы, и поток завершается в фибере созданном в другом модуле.
|