Самовыгружающийся DLL-модуль
Модераторы: Hawk, Romeo, Absurd, DeeJayC, WinMain
BBB Я же сразу сказал, что не знаю.
WinMain Что за привычка отвечать не на поставленный вопрос, а говорить что знаеш. Он не спрашивал как система работает с ресурсами, а просил показать как "выгрузиться из памяти". Это разные задачи: организация выполнения модулей, находяшихся в dll и выгрузка этих модулей из памяти.
WinMain Что за привычка отвечать не на поставленный вопрос, а говорить что знаеш. Он не спрашивал как система работает с ресурсами, а просил показать как "выгрузиться из памяти". Это разные задачи: организация выполнения модулей, находяшихся в dll и выгрузка этих модулей из памяти.
Оптимизация по скорости:
#define while if
Оптимизация по размеру:
#define struct union
#define while if
Оптимизация по размеру:
#define struct union
Во-первых, я действительно говорю то, что знаю...
Во-вторых, очитить оперативную память от ненужных ресурсов не так уж сложно: достаточно оставить компьютер в покое минут на 10-15 (попить чайку, покурить, сходить в туалет), а система сама выгрузит из памяти всё лишнее. Либо загрузить в память другие модули, которые вытеснят неиспользуемые образы.
Вопрос в другом: кого это волнует на уровне прикладных задач?
Главное, чтобы его плагины функционировали правильно. А управление внутренними ресурсами ядра операционной системы - это на столько узко-специализированная задача для системных программистов, что на этом форуме её даже обсуждать бесполезно.
Во-вторых, очитить оперативную память от ненужных ресурсов не так уж сложно: достаточно оставить компьютер в покое минут на 10-15 (попить чайку, покурить, сходить в туалет), а система сама выгрузит из памяти всё лишнее. Либо загрузить в память другие модули, которые вытеснят неиспользуемые образы.
Вопрос в другом: кого это волнует на уровне прикладных задач?
Главное, чтобы его плагины функционировали правильно. А управление внутренними ресурсами ядра операционной системы - это на столько узко-специализированная задача для системных программистов, что на этом форуме её даже обсуждать бесполезно.
- Naeel Maqsudov
- Сообщения: 2570
- Зарегистрирован: 20 фев 2004, 19:17
- Откуда: Moscow, Russia
- Контактная информация:
Народ, давайте конструктивно, без флейма.
Скажем так: Побудить систему к выгрузке иначе как с помощью FreeLibrary можно?
Если нет, то тема как бы исчерпана.
Скажем так: Побудить систему к выгрузке иначе как с помощью FreeLibrary можно?
Если нет, то тема как бы исчерпана.
Спасибо всем за участие, но вы как-то ушли от темы.
Меня, как сказал WinMain, интересует в первую очередь правильная работа моего плагина в многопоточном режиме, в данном случае нужно просто корректно освободить модуль после завершения потоковой процедуры. Мне нужна всего лишь грамотная реализация этой логической схемы.
О физической зачистке памяти здесь речь вообще не шла, а зачем понадобилось разводить эту дискуссию? Лично мне не понятно.
В общем так, я решил вместо CALLBACK-функции использовать указатель на интерфейс, в котором будет вызываться метод UnloadMe(). Класс CPluginManager должен будет имплементировать этот интерфейс и данный метод соответственно. Кроме этого мне нужно в классе CPluginManager сделать получение списка имеющихся плагинов и их функциональное назначение, т.е. краткое описание того, что каждый из них делает. Потому как в меню пользователя должны отображаться не имена файлов DLL-модулей, а набор тех действий, который они выполняют (например: "Загрузка данных по сети", "Печать Счёт-фактуры" и др.), и по выбору пользователем того или иного пункта меню, CPluginManager должен загрузить соответствующий плагин и запустить в нём нужную процедуру. А после завершения процедуры через передаваемый интерфейс будет вызываться метод UnloadMe(), который и будет выгружать (освобождать) этот модуль.
Меня, как сказал WinMain, интересует в первую очередь правильная работа моего плагина в многопоточном режиме, в данном случае нужно просто корректно освободить модуль после завершения потоковой процедуры. Мне нужна всего лишь грамотная реализация этой логической схемы.
О физической зачистке памяти здесь речь вообще не шла, а зачем понадобилось разводить эту дискуссию? Лично мне не понятно.
В общем так, я решил вместо CALLBACK-функции использовать указатель на интерфейс, в котором будет вызываться метод UnloadMe(). Класс CPluginManager должен будет имплементировать этот интерфейс и данный метод соответственно. Кроме этого мне нужно в классе CPluginManager сделать получение списка имеющихся плагинов и их функциональное назначение, т.е. краткое описание того, что каждый из них делает. Потому как в меню пользователя должны отображаться не имена файлов DLL-модулей, а набор тех действий, который они выполняют (например: "Загрузка данных по сети", "Печать Счёт-фактуры" и др.), и по выбору пользователем того или иного пункта меню, CPluginManager должен загрузить соответствующий плагин и запустить в нём нужную процедуру. А после завершения процедуры через передаваемый интерфейс будет вызываться метод UnloadMe(), который и будет выгружать (освобождать) этот модуль.
[off]
Да, только на это нужно время, которого может и не быть.
[/off]
Это студеческая привычка. Отвечать не на поставленный вопрос, а говорить что знаеш.WinMain писал(а):Во-первых, я действительно говорю то, что знаю...
Во-вторых, очитить оперативную память от ненужных ресурсов не так уж сложно: достаточно оставить компьютер в покое минут на 10-15 (попить чайку, покурить, сходить в туалет), а система сама выгрузит из памяти всё лишнее.
Да, только на это нужно время, которого может и не быть.
[/off]
Выражаться надо точнее, а то мы тут устроили диспут, а выгрузка из памяти совсем не нужна.Decoder писал(а):Т.е. загрузил плагин, создал поток, запустил процедуру на выполнение, а дальше по завершении процедуры модуль сам должен выгрузиться из памяти.
Оптимизация по скорости:
#define while if
Оптимизация по размеру:
#define struct union
#define while if
Оптимизация по размеру:
#define struct union
Ну хорошо, а что ты сам-то подразумеваешь под словом "выгрузка" из памяти, если не освобождение ранее занятого пространства или отказ от использования какого-то системного объекта? Как ты себе этот процесс по-другому представляешь?
Может я что-то ещё должен сделать с уже неиспользуемым системным ресурсом?
Может я что-то ещё должен сделать с уже неиспользуемым системным ресурсом?
А это хорошая идея: периодически предлагать пользователю сделать технологический перерыв.достаточно оставить компьютер в покое минут на 10-15 (попить чайку, покурить, сходить в туалет), а система сама выгрузит из памяти всё лишнее.
Информацию о плагине можно записать в ресурсы, а именно в секцию VERSIONINFO, параметр FileDescription. Тогда этот текст будет виден в Проводнике. Если не знаешь, как брать информацию из VERSIONINFO, то я об этом позже могу написать. Все планигы нужно поместить в отдельную папку, например PLUGINS и с помощью функций FindFirstFile, FindNextFile получить список имеющихся модулей. Ассоциативно связать в программе информацию о плагине с именем его файла можно с помощью контейнера std::map.
Спасибо, WinMain. Интересное решение.
В общем так, чтобы никто мне больше не морочил голову с загрузкой/выгрузкой DLL-модуля и чтобы окончательно закрыть этот вопрос, я провёл следующий эксперимент:
Создал DLL-модуль, в котором объявил глобальный объект в виде класса, у которого в конструкторе на консоль отправляется текст "Глобальный конструктор", а из деструктора отправляется текст "Глобальный деструктор".
В коде так выглядит:
Далее создал приложение, которое загружает этот модуль и тут же его освобождает.
Вот как оно выглядит в коде:
После запуска приложения на экране появились строки
Таким образом можно сделать вывод, что если вызывается деструктор класса, то значит этот объект каким-то образом удаляется из памяти.
А это значит, что модуль всё-таки выгружается из памяти, иначе как ещё это можно было бы объяснить?
Продолжим эксперимент дальше. Пусть функция LoadLibrary() вызывается дважды, а FreeLibrary() только один раз.
В этом случае на экране появилось только одна надпись:
Остальные утверждения про невозможность выгрузить DLL из памяти - это не более чем домыслы.
В общем так, чтобы никто мне больше не морочил голову с загрузкой/выгрузкой DLL-модуля и чтобы окончательно закрыть этот вопрос, я провёл следующий эксперимент:
Создал DLL-модуль, в котором объявил глобальный объект в виде класса, у которого в конструкторе на консоль отправляется текст "Глобальный конструктор", а из деструктора отправляется текст "Глобальный деструктор".
В коде так выглядит:
Код: Выделить всё
// FreeLib.cpp : Defines the entry point for the DLL application.
#include "stdafx.h"
#include <tchar.h>
BOOL PrintText(LPCTSTR szText)
{
static HANDLE hConsole = ::GetStdHandle(STD_OUTPUT_HANDLE);
//
DWORD dw(0);
return ::WriteConsole(hConsole, szText, ::lstrlen(szText), &dw, NULL);
}
class Global
{
public:
Global()
{
PrintText(_T("Глобальный конструктор...\r\n"));
}
~Global()
{
PrintText(_T("Глобальный деструктор...\r\n"));
}
} _global;
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved)
{
return TRUE;
}
Вот как оно выглядит в коде:
Код: Выделить всё
#include "stdafx.h"
#include "conio.h"
int _tmain(int argc, _TCHAR* argv[])
{
HMODULE hModule = ::LoadLibrary(_T("FreeLib.dll"));
if (hModule != NULL)
{
::FreeLibrary(hModule);
}
_getch();
return 0;
}
Само приложение при этом не завершает работу, поскольку этому препятствует функция _getch, ожидающая ввод символа с клавиатуры.Глобальный конструктор...
Глобальный деструктор...
Таким образом можно сделать вывод, что если вызывается деструктор класса, то значит этот объект каким-то образом удаляется из памяти.
А это значит, что модуль всё-таки выгружается из памяти, иначе как ещё это можно было бы объяснить?
Продолжим эксперимент дальше. Пусть функция LoadLibrary() вызывается дважды, а FreeLibrary() только один раз.
Код: Выделить всё
#include "stdafx.h"
#include "conio.h"
int _tmain(int argc, _TCHAR* argv[])
{
::LoadLibrary(_T("FreeLib.dll"));
HMODULE hModule = ::LoadLibrary(_T("FreeLib.dll"));
if (hModule != NULL)
{
::FreeLibrary(hModule);
}
_getch();
return 0;
}
В итоге окончательный вывод таков: если количество вывовов FreeLibrary равняется количеству ранее вызванных LoadLibrary, то модуль просто выгружается из памяти и всё.Глобальный конструктор...
Остальные утверждения про невозможность выгрузить DLL из памяти - это не более чем домыслы.
Уже неверный вывод. Если вызывается деструктор класса, то работа с этим экземпляром завершена. Больше ничего от сюда не следует. С чего ты решил, что объект был выгружен из памяти ?Decoder писал(а):Таким образом можно сделать вывод, что если вызывается деструктор класса, то значит этот объект каким-то образом удаляется из памяти.
А это значит, что модуль всё-таки выгружается из памяти, иначе как ещё это можно было бы объяснить?
Как-то винда выгружает библиотеки. Кто знает способ это сделать ?
Оптимизация по скорости:
#define while if
Оптимизация по размеру:
#define struct union
#define while if
Оптимизация по размеру:
#define struct union
А каким ещё образом можно завершить работу с глобальным объектом, кроме как выгрузкой модуля или завершением работы всего приложения?
Можешь назвать какой-нибудь другой способ?
Можешь назвать какой-нибудь другой способ?