Dlaczego wywołanie w wątku SDL_GL_MakeCurrent() powoduje mem leak?

0

Tworzę 2 nowe wątki i 2 konteksty, po jednym na wątek, plus kontekst główny. Wywołanie SDL_GL_MakeCurrent(window, XXXcontext) powoduje memleak. Problem znika gdy używamy tej funkcji w głównym wątku, ale przecież tutaj chodzi o to, żeby było kilka wątków. Również nie ma problemu gdy SDL_GL_MakeCurrent(window, XXXcontext) jest komentarzem, a nie wywołaniem.
Dlaczego tak się dzieje?

ustawienia okna

SDL_GLContext mainContext = nullptr;
SDL_GLContext thread1Context = nullptr;
SDL_GLContext thread2Context = nullptr;

SDL_Window* window = nullptr;

SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 6);
//--------------------
SDL_GL_SetAttribute(SDL_GL_SHARE_WITH_CURRENT_CONTEXT, 1);
//--------------------
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
window = SDL_CreateWindow("window", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1600, 900, SDL_WINDOW_OPENGL);

thread1Context = SDL_GL_CreateContext(window);
thread2Context = SDL_GL_CreateContext(window);
mainContext = SDL_GL_CreateContext(window);

//glew
InitOpengl();

wersja pętli z memleakiem

void MainLoop() 
{
	while (!quit)
	{
		thread1 = std::thread([&]() {
			SDL_GL_MakeCurrent(window, thread1Context);

			//SDL_GL_MakeCurrent(window, nullptr);
		});	

		thread2 = std::thread([&]() {
			SDL_GL_MakeCurrent(window, thread2Context);

			//SDL_GL_MakeCurrent(window, nullptr);
		});

		thread1.join();
		thread2.join();
	}

	SDL_GL_DeleteContext(thread1Context);
	SDL_GL_DeleteContext(thread2Context);
	SDL_GL_DeleteContext(mainContext);

	SDL_DestroyWindow(window);
}

i bez memleaku ale też bez wątków

void MainLoop() 
{
	while (!quit)
	{
		//thread1 = std::thread([&]() {
			SDL_GL_MakeCurrent(window, thread1Context);

			//SDL_GL_MakeCurrent(window, nullptr);
		//});	

		//thread2 = std::thread([&]() {
			SDL_GL_MakeCurrent(window, thread2Context);

			//SDL_GL_MakeCurrent(window, nullptr);
		//});

		//thread1.join();
		//thread2.join();
	}

	SDL_GL_DeleteContext(thread1Context);
	SDL_GL_DeleteContext(thread2Context);
	SDL_GL_DeleteContext(mainContext);

	SDL_DestroyWindow(window);
}
1

A czy w dokumentacji SDL jest coś na temat gwarancji bezpieczeństwa używania API wielowątkowo?
Jeśli ta biblioteka ma jakiś ukryty stan bez synchronizacji to "sorry taki mamy klimat".
To jest jeden z powodów dlaczego nie powinno się używać zmiennych globalnych.

FAQDevelopment - SDL Wiki'

Can I call SDL video functions from multiple threads?

No, most graphics back ends are not thread-safe, so you should only call SDL video functions from the main thread of your application.

0

        std::thread thread;
        SDL_GLContext mainContext = nullptr;
	SDL_GLContext sharedContext = nullptr;

	SDL_Window* window = nullptr;

	App()
	{
		SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
		SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 6);
		SDL_GL_SetAttribute(SDL_GL_SHARE_WITH_CURRENT_CONTEXT, 1);
		SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
		window = SDL_CreateWindow("window", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1600, 900, SDL_WINDOW_OPENGL);

		sharedContext = SDL_GL_CreateContext(window);
		mainContext = SDL_GL_CreateContext(window);

		InitOpengl();
       }

       ~App()
       {
           thread.join();
       }

	void App::ThreadLoop()
	{
		thread = std::thread([&]() {
			while (!quit) {
				SDL_GL_MakeCurrent(window, sharedContext);


				SDL_GL_MakeCurrent(window, nullptr);
			}
		});
	}

	void App::MainLoop() override
	{
		ThreadLoop();
		while (!quit)
		{
			while (SDL_PollEvent(&event)) {
				if (event.type == SDL_QUIT) {
					quit = true;
				}
			}
 
                        SDL_GL_MakeCurrent(window, mainContext);
	                SDL_GL_SwapWindow(window);
		}

		SDL_GL_DeleteContext(sharedContext);
		SDL_GL_DeleteContext(mainContext);

		SDL_DestroyWindow(window);
	}

I tu nie ma wycieku nawet jak SDL_GL_MakeCurrent() jest w innym wątku, ale jak już bym chciał w tym wątku stworzyć kolejny wątek np.


void ThreadLoop()
	{
		thread = std::thread([&]() {
			while (!quit) {
				std::thread thread2([&]() {
					SDL_GL_MakeCurrent(window, sharedContext);


					SDL_GL_MakeCurrent(window, nullptr);		
				});
				thread2.join();
			}
		});
	}

to wyciek znów jest.

Pewnie masz rację z tą synchronizacją. Ale w takim wypadku w jaki sposób mogę to naprawić? Próbowałem już mutexem, nadal to samo, więc no...

0

Przyjrzałbym się tym trzem linijkom kodu:

 thread1Context = SDL_GL_CreateContext(window);
 thread2Context = SDL_GL_CreateContext(window); 
 mainContext = SDL_GL_CreateContext(window);

Czy przypadkiem nie jest tak, że zwracane są tutaj wskaźniki do tego samego kontekstu?

0

Żeby móc naprawić najpierw trzeba wiedzieć co naprawić. Jeżeli nie wiesz gdzie i co cieknie, to masz ręce związane. Gdb twoim przyjacielem.

0

A może lepiej wyjaśnij po co ci wątki?
Jestem pewien, że ludzie pisali dużo bardziej skomplikowane gry bez użycia wątków na dużo słabsze maszyny i nic im się nie zacinało.
Ja wiem, że teraz jest moda na wielowątkowość, bo procesory mają coraz więcej rdzeni, ale programowanie wielowątkowe jest o wiele bardziej trudne od zwykłego programowania, szczególnie jeśli ktoś jeszcze dobrze nie opanował programowania.

0
MarekR22 napisał(a):

A może lepiej wyjaśnij po co ci wątki?

Żeby renderować grafikę w tym samym momencie co, np. poruszanie oknem, żeby apka się nie zacinała. Żeby nauczyć się wielowątkowości .
Żeby ładować assety i w tym samym momencie pokazać na ekranie pasek postępu, a nie czarny ekran i brak możliwości jakiejkolwiek interakcji.
Czy nie ładniej to będzie wyglądać?

Jestem pewien, że ludzie pisali dużo bardziej skomplikowane gry bez użycia wątków na dużo słabsze maszyny i nic im się nie zacinało.
Ja wiem, że teraz jest moda na wielowątkowość, bo procesory mają coraz więcej rdzeni, ale programowanie wielowątkowe jest o wiele bardziej trudne od zwykłego programowania, szczególnie jeśli ktoś jeszcze dobrze nie opanował programowania.

Umiem napisać kod na jednym wątku bez żadnych problemów, dlatego teraz chciałbym się zająć wielowątkowością.

0

Co do przesuwania okna: https://stackoverflow.com/a/27195881/1387438
Co zacinek: to bierzesz profiler (ten MSVS jest dość przyjemny) ustalasz gdzie i dlaczego kod się przycina i rozwiązujesz problem tam. Skill bardziej cenny niż wpychanie wielowątkowości na siłę.

Co do uczenia się wielowątkowości: polecam unikać jak ognia dopóki w normalnym programowaniu nie poczujesz się pewnie.
Największy problem z wielowątkowością: możesz stworzyć kod, który będzie ci się wydawał prawidłowy, będzie działać zawsze u ciebie, a innych będzie się wieszał lub crashował co 5 minut. Programowanie wątków wymaga o wiele większej dyscypliny podczas pisania kodu.

Większość kursów wielowątkowości demonstruje ją na zbyt mało wymagających problemach, przez co efektywność kodu jest mniejsza, a u ucznia wyrabia się nawyk wpychania wątków do każdego głupiego zadania.

0

Co do przesuwania okna: https://stackoverflow.com/a/27195881/1387438
Co zacinek: to bierzesz profiler (ten MSVS jest dość przyjemny) ustalasz gdzie i dlaczego kod się przycina i rozwiązujesz problem tam. Skill bardziej cenny niż wpychanie wielowątkowości na siłę.

Nie chodzi mi tu o ścinki, że o lagi, że za mało FPS, czy ms., a z profilera też umiem korzystać i to robię. Chodzi mi o to, że jeśli grafika jest renderowana, np. katscenka, i w tym momencie złapie pasek przesuwania okna (ten standardowy, a nie jakiś stworzony przez nasze gui), to grafika katscenka stanie w miejscu, bo korzystamy z eventów okna. Sprawdzę link który podałeś jak wrócę z pracy.

Co do uczenia się wielowątkowości: polecam unikać jak ognia dopóki w normalnym programowaniu nie poczujesz się pewnie.
Największy problem z wielowątkowością: możesz stworzyć kod, który będzie ci się wydawał prawidłowy, będzie działać zawsze u ciebie, a innych będzie się wieszał lub crashował co 5 minut. Programowanie wątków wymaga o wiele większej dyscypliny podczas pisania kodu.

Większość kursów wielowątkowości demonstruje ją na zbyt mało wymagających problemach, przez co efektywność kodu jest mniejsza, a u ucznia wyrabia się nawyk wpychania wątków do każdego głupiego zadania.

Czuje się aż za pewnie w normalnym programowaniu (jako programowaniu, bo czasami problem nie tkwi w programowaniu a np. w matematyce). Raczej nie korzystam z kursów, wole rozmowy na gdc czy cppcon i nie wpycham wszędzie wielowątkowości ale akurat renderowanie wielowątkowe jest ważnym tematem moim zdaniem,

1 użytkowników online, w tym zalogowanych: 0, gości: 1