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

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

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

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

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

Ответ
 
Опции темы Поиск в этой теме
Старый 09.02.2013, 19:30   #1
220Volt
Форумчанин
 
Регистрация: 14.12.2012
Сообщений: 668
По умолчанию Завершение потоков в dll при выгрузке

Доброго времени суток.
exe:
Код:
int _tmain(int argc, _TCHAR* argv[])
{
	HINSTANCE hMyDll = LoadLibraryA("Th_lib.dll");
	typedef void (__cdecl *Dll_fn)();
	Dll_fn f = (Dll_fn)GetProcAddress(hMyDll, "fn");
	(*f)();
	FreeLibrary(hMyDll);

	return 0;
}
dll:
Код:
#include <thread>

class Q
{
	static void thFn()   { MessageBoxA(NULL, "thFn", "", MB_OK); }  // Не получаем
	std::thread th;
public:
	~Q()		
	{ 
		if(th.joinable()) th.join(); 
		MessageBoxA(NULL, "Destructor", "", MB_OK);  // Не получаем
	}
	void Run()  { th = std::thread(thFn); }
}m_th;

void __cdecl fn()   { m_th.Run(); }    // Экспортируемая
Хочу в dll создать потоки, а завершить их при выгрузке dll (сделать deinit не вариант, exe часть недоступна, точнее жестко ограничена). Программа виснет. Пробовал действия раскидать в dllmain – не помогает. Получается только через winapi – TerminateThread(). Можно ли без winapi? Почему схема не работает?
220Volt вне форума Ответить с цитированием
Старый 09.02.2013, 21:48   #2
Dizelektwo
Пользователь
 
Регистрация: 05.04.2012
Сообщений: 56
По умолчанию

Можно ли без winapi?
Нельзя.
а завершить их при выгрузке dll
Потоки погибают при выгрузке. Двойная работа?
Dizelektwo вне форума Ответить с цитированием
Старый 10.02.2013, 05:14   #3
220Volt
Форумчанин
 
Регистрация: 14.12.2012
Сообщений: 668
По умолчанию

Цитата:
...
Потоки погибают при выгрузке. Двойная работа?
Тут и проблема - не погибают, а виснут.

P.S. Больший интерес для меня представляет понимание причины ошибки, а не решение (знаю как).

Последний раз редактировалось 220Volt; 10.02.2013 в 05:59.
220Volt вне форума Ответить с цитированием
Старый 10.02.2013, 09:56   #4
waleri
Старожил
 
Регистрация: 13.07.2012
Сообщений: 6,330
По умолчанию

Потоки сами собой не завершаются - надо им каким-то образом посылать сигнал, чтом им надо завершаться. Как вы будете это делать, зависит только от вас.
waleri на форуме Ответить с цитированием
Старый 10.02.2013, 18:50   #5
Dizelektwo
Пользователь
 
Регистрация: 05.04.2012
Сообщений: 56
По умолчанию

Поток живет в адресном пространстве процесса от замапанной длл. Что при выгрузке exe, что при выгрузке dll - поток дохнет.


p.s Поток как раз таки завершается сам после выполнения операции N, так что терминэйт придется вызывать в любом случае, т.е раннее завершение всегда будет критическим.

Последний раз редактировалось Dizelektwo; 10.02.2013 в 18:52.
Dizelektwo вне форума Ответить с цитированием
Старый 11.02.2013, 06:16   #6
220Volt
Форумчанин
 
Регистрация: 14.12.2012
Сообщений: 668
По умолчанию

Наверное, я немного не четко выразился.
Мне кажется странным поведение стандартного класса thread. Например:
Код:
#include <windows.h>
#include <thread>
class Q
{
	std::thread th;
	static void thF()
	{
		for(int ret = 5;  ret > 0;  --ret)
			MessageBoxA(NULL, "", "", MB_OK);
	}
public:
	Q()   { th = std::thread(thF); }
	~Q()   { if(this->th.joinable())   this->th.join(); }
}t;

int main()
{
    return 0;
}
работает странно, а такой ведет себя нормально:
Код:
#include <windows.h>
#include <thread>
class Q
{
	std::thread th;
	static void thF()
	{
		for(int ret = 5;  ret > 0;  --ret)
			MessageBoxA(NULL, "", "", MB_OK);
	}
public:
	Q()   { th = std::thread(thF); }
	~Q()   { if(this->th.joinable())   this->th.join(); }
};

int main()
{
    Q t;
    return 0;
}
Странность первого примера – не закрытие консоли после завершения функции потока th (cледовательно, главный поток подвисает в th.join() даже после завершения потока th). В dll поведение тоже непонятное. В общем не понимаю я этот класс, решил пока отказаться от него в пользу winapi (чтобы не искать непонятных ошибок). Такой класс, без использования новых примочек, работает так, как я ожидаю (5 MessageBox с последующим закрытием консоли):
Код:
#include <windows.h>
#include <process.h>
class Q
{
	HANDLE th;
	static unsigned int __stdcall thF(void *)
	{
		for(int ret = 5;  ret > 0;  --ret)
			MessageBoxA(NULL, "", "", MB_OK);
		return 0;
	}
public:
	Q()   { th = (HANDLE)_beginthreadex(NULL, 0, thF, nullptr, 0, NULL); }
	~Q()   { WaitForSingleObject(th, INFINITE); CloseHandle(th); }
}t;

int main()
{
    return 0;
}

Последний раз редактировалось 220Volt; 11.02.2013 в 07:39.
220Volt вне форума Ответить с цитированием
Старый 11.02.2013, 08:54   #7
waleri
Старожил
 
Регистрация: 13.07.2012
Сообщений: 6,330
По умолчанию

Цитата:
Сообщение от Dizelektwo Посмотреть сообщение
Поток живет в адресном пространстве процесса от замапанной длл. Что при выгрузке exe, что при выгрузке dll - поток дохнет.
Вы еще скажите "при выключении питания". Понятно, что при выгрузке DLL поток *сломается* (при чем не обязательно сразу), что приведет к *аварийному* завершению. Речь шла о том, что для *нормального* завершения нужно самому организовать посылку сигнала.

Впрочем так или иначе, вопрос вообще оказался не в этом.

Я бы только добавил, что аварийное завершение потока чревато утечкой ресурсов.
waleri на форуме Ответить с цитированием
Старый 11.02.2013, 09:32   #8
220Volt
Форумчанин
 
Регистрация: 14.12.2012
Сообщений: 668
По умолчанию

Код:
#include <windows.h>
#include <thread>
class Q
{
	std::thread th;
	static void thF()
	{
		for(int ret = 5;  ret > 0;  --ret)
			MessageBoxA(NULL, "", "", MB_OK);
	}
public:
	Q()   { th = std::thread(thF); }
	~Q()   { if(this->th.joinable())   this->th.join(); }
}t;

int main()   // Консоль не закрывается, главный поток виснет в join()
{
    return 0;
}
Код:
#include <windows.h>
#include <thread>
class Q
{
	std::thread th;
	static void thF()
	{
		for(int ret = 5;  ret > 0;  --ret)
			MessageBoxA(NULL, "", "", MB_OK);
	}
public:
	Q()   { th = std::thread(thF); }
	~Q()   { if(this->th.joinable())   this->th.join(); }
};

int main()   // ок
{
    Q t;
    return 0;
}
Я компилировал это на Visual Studio express 2012. Если кто-то находит странным не закрытие консоли в первом случаи, имеет иной компилятор и желание поэкспериментировать, предлагаю протестировать и сообщить о результатах. Мне кажется, что какая-то ошибка на стороне студии.
220Volt вне форума Ответить с цитированием
Ответ


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

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
bass.dll аварийное завершение загрузки музыки из сети Mr_F Мультимедиа в Delphi 5 16.08.2013 19:45
Завершение приложения при ожидании accept() GrayGhost C/C++ Сетевое программирование 2 17.10.2012 05:33
Формат столбца при выгрузке в Эксель Swatch Microsoft Office Access 3 02.11.2010 19:19
завершение цикла при нажатии клавиши LLIyPI/IK Общие вопросы C/C++ 8 12.02.2010 13:29
Крах при выгрузке DLL prizrak1390 Общие вопросы Delphi 15 11.09.2009 19:08