Autor Wątek: [SDL]Wątki i wyciek pamięci  (Przeczytany 2300 razy)

Offline Furry

  • Użytkownik
    • DevBlog

# Grudzień 09, 2010, 19:05:21
Ostatnio zauważyłem dziwną rzecz, że jeśli stworzę wątek przy pomocy SDL_CreateThread to nawet jeśli jego funkcja zakończy się przez return 0 to pozostawia on po sobie 8KB. Czy trzeba jakoś dodatkowo kasować wątki? Z tego co czytałem wystarczy, że jego funkcja się zakończy, a tu takie coś... Czy ktoś wie jak zwolnić te 8KB? Może to nie jest dużo ale jak odpala się coś na wątku kilka razy to zaczyna ta zmarnowana pamięć szybko rosnąć.

Offline Mr. Spam

  • Miłośnik przetworów mięsnych

Offline segfault

  • Użytkownik

# Grudzień 11, 2010, 18:30:05
Po zakończeniu działania wątku pewne dane zostają nadal w pamięci, np. jakbyś chciał pobrać kod z jakim zakończył sie wątek. SDL_WaitThread powinno pomóc.

Offline Furry

  • Użytkownik
    • DevBlog

# Grudzień 11, 2010, 18:36:44
ale WaitThread robi takie coś, że czekam, w wątku w którym tworzę nowy wątek, na jego zakończenie, a przecież nie o to mi chodzi.

Offline segfault

  • Użytkownik

# Grudzień 11, 2010, 18:40:54
Wiem, ale oprócz tego zwalnia zasoby powiązane z wątkiem. Sprawdziłem w źródłach SDLa. W implementacji dla win32 dopiero w WaitThread jest zamykany uchwyt wątku za pomocą CloseHandle. Podobnie w implementacji używającej pthreads, pthread_join jest wywołane z SDL_WaitThread. Do czasu join lub zakończenia twojego programu pewne zasoby wątku pozostają w systemie, tzw. wątek zoombie.

Offline Furry

  • Użytkownik
    • DevBlog

# Grudzień 11, 2010, 18:45:12
No tak ale ja nie chciałbym czekać aż odpalony wątek się zakończy. Przecież po to go odpalam by wątek główny mógł się swoimi sprawami zająć, a nowy wątek swoimi.

Offline segfault

  • Użytkownik

# Grudzień 11, 2010, 18:55:50
Nie musisz czekać. Pewnie w jakiś sposób synchronizujesz wątki lub odbierasz dane przetworzone przez wątek. Jeśli już wiesz, że ten wątek sie zakończył wywołujesz SDL_WaitThread. WaitThread zwróci wartość zwróconą przez wątek bez czekania.

EDIT: Cytat z dokumentacji
Cytuj
(SDL 1.2.7) Even after the procedure started in the thread returns, there still exist some resources allocated to the thread. To free these resources, use SDL_WaitThread to wait for the thread to finish and obtain the status code of the thread. If not done so, SDL_CreateThread will hang after about 1010 successfully created threads (tested on GNU/Linux).
http://sdl.beuc.net/sdl.wiki/SDL_CreateThread
« Ostatnia zmiana: Grudzień 11, 2010, 18:57:43 wysłana przez segfault »

Offline Furry

  • Użytkownik
    • DevBlog

# Grudzień 11, 2010, 19:06:33
No właśnie jest problem bo nie wiem kiedy się kończy, po prostu nie sprawdzam tego...

Offline bies

  • Użytkownik

# Grudzień 11, 2010, 19:20:53
Pomijając przez chwilę, że wolę Boost.Threads...

Możesz zrobić (na Windows):
SDL_Thread *thread = SDL_CreateThread(...);
CloseHandle(thread->handle);
wątek będzie odłączony (detached w terminologii pthreads). Tylko pamiętaj, że na takim wątku nie wolno Ci praktycznie nic zrobić.

Offline Furry

  • Użytkownik
    • DevBlog

# Grudzień 11, 2010, 19:26:23
Czy w boost.threads taka operacja wykonuje się samoczynnie po zakończeniu wątku?
Wiesz dla mnie to praktycznie bez różnicy czy do wątków użyję SDLa czy Boosta.

Offline bies

  • Użytkownik

# Grudzień 11, 2010, 19:31:50
Czy w boost.threads taka operacja wykonuje się samoczynnie po zakończeniu wątku?
Wiesz dla mnie to praktycznie bez różnicy czy do wątków użyję SDLa czy Boosta.
Tak. Każdy wątek do którego nie ma odniesień jest automatycznie odłączony. Prawdę powiedziawszy dziwne, że SDL nie oferuje ładnej funkcji SDL_DetachThread();

// edit
Choć z drugiej strony...
void SDL_DeatachThread(SDL_Thread *t) {
    if (thread && thread->handle)
#if defined(__WIN32__)
        CloseHandle(thread->handle);
#else
        pthread_detach(thread->handle);
#endif
}
+- obsługa błędów.
« Ostatnia zmiana: Grudzień 11, 2010, 19:51:44 wysłana przez bies »

Offline Furry

  • Użytkownik
    • DevBlog

# Grudzień 11, 2010, 19:38:09
Fakt, mnie też to zdziwiło, po prostu myślałem, że samo z siebie kasuje wątki po zakończeniu ich działania,a tu nagle patrzę, że jak zostawiłem kompa z otwartym skompilowanym projektem na 2h to nagle wykorzystana pamięć mi podskoczyła o kilkanaście mega:P

Offline segfault

  • Użytkownik

# Grudzień 11, 2010, 19:54:05
void SDL_DeatachThread(SDL_Thread *t) {
    if (thread->handle)
#if defined(__WIN32__)
        CloseHandle(thread->handle);
#else
        pthread_detach(thread->handle);
#endif
}
+- obsługa błędów.

Niestety nie zadziała, ponieważ SDL_Thread jest typem niejawnym (opaque). Zadeklarowany w nagłówkach jako struct SDL_Thread. Po dodaniu
#if defined(__WIN32)
struct SDL_Thread {
  Uint32 threadid;
  HANDLE handle;
};
#else
struct SDL_Thread
{
  Uint32 threadid;
  pthread_t handle;
};
#endif
zadziała, ale rozwiązanie staje się jeszcze brzydsze i coraz bardziej polega na wnętrznościach SDLa.

Offline bies

  • Użytkownik

# Grudzień 11, 2010, 19:58:28
Owszem, pierwszy kod z bezpośrednim CloseHandle() też polega na wnętrznościach SDL. Dlatego dziwię się, że nie ma SDL_DetachThread() w SDL.