Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

[C++] gdb problem z silnikiem gry przy większej ilości graczy

Ostatnio zmodyfikowano 2024-09-24 08:14
Autor Wiadomość
dunno
Temat założony przez niniejszego użytkownika
[C++] gdb problem z silnikiem gry przy większej ilości graczy
» 2024-09-15 12:26:35
Kilka razy byliście w stanie nakierować mnie na rozwiązanie problemu, w związku z tym i tym razem zwracam się o pomoc.
Posiadam skompilowany na Debian 11 silnik gry mmorpg, lecz losowo sypie mi błędami crashując cały serwer gry.
---
Pierwszy błąd jaki się pojawia to:
Logi gdb1: https://pastebin.com/npiVyx4V.
Funkcje Spawn::idle oraz SpawnManager::checkSpawns https://pastebin.com/VW5zak7N.
C/C++
++it; // LINIA 445 CRASH

---
Drugi błąd jaki się często pojawia przy dużej liczbie graczy:
Logi gdb2: https://pastebin.com/LUy220V1.
Funkcje Game::placeCreature oraz Game::sendAddThing oraz Game::getSpectators oraz Map::getSpectators
https://pastebin.com/FWJLAcFy.
C/C++
sendAddThing( NULL, c->pos, c ); // linia 1845 CRASH
getSpectators( Range( pos, true ), list, false, false ); // LINIA 8249 CRASH
map->getSpectators( range, list, onlyPlayers, checkDuplicate ); // LINIA 4502 CRASH
if( * cit ) // dodane przeze mnie dla pewnosci // linia 327 CRASH
   

Co widać w logach
cit = non - dereferenceable iterator for std::vector

it = non - dereferenceable iterator for std::vector



---
Po tych dwóch błędach w czasie uruchomionego silnika gry, zaczął pojawiać się kolejny trzeci błąd
Logi gdb3: https://pastebin.com/SwHSefRv. (częsciowe)
I o ile dwa pierwsze bledy byly podczas uruchomionego silnika gry to trzeci blad spowodowal ze juz nie chciało załadować silnika gry, pomógł reboot systemu

Jakieś rady? wskazówki? może znowu naprowadzicie mnie na rozwiązanie problemu?:D
P-181590
pekfos
» 2024-09-15 14:39:59
Pierwszy przypadek w kodzie wygląda poprawnie. Takie sytuacje to zwykle niesynchronizowany dostęp do kontenera (zakładam że nie, bo jest jakiś mutex w Game::checkSpawns, pytanie czy pokrywa wszystkie przypadki), albo uszkodzenie pamięci. Myślę że druga opcja jest bardziej prawdopodobna i też by tłumaczyła różne inne przypadki losowych awarii. Obstawiam że gdzieś masz wiszące wskaźniki na usunięte obiekty i próbujesz coś na nich robić. Taki dostęp do pamięci nie musi wywołać awarii sam z siebie, ale jak ten obszar został zaalokowany na coś innego to uszkodzisz dane i wywołasz błąd w losowym miejscu. Mając coredump można by się pewnie dowiedzieć więcej, ale to trochę beznadziejna sprawa tłumaczyć to krok po kroku przez forum. Możesz spróbować odpalić serwer z Valgrindem.
https://stackoverflow.com/questions/13665076/using-valgrind-to-debug-use-after-free

Drugi przypadek jest ciekawszy bo w iteratorze wektora dużo mniej może się zepsuć. Należałoby sprawdzić jak dokładnie wygląda cit i tile->creatures. W zasadzie wyjaśnienia mogą być takie same jak w pierwszym przypadku. Albo inny wątek usunął coś z wektora i cit stało się niepoprawne, albo analogiczna sytuacja zaszła w wyniku uszkodzenia pamięci.

Za mało informacji o trzecim przypadku.
P-181591
dunno
Temat założony przez niniejszego użytkownika
» 2024-09-15 19:11:54
Mając coredump można by się pewnie dowiedzieć więcej
W jaki sposób? bo to jest bt full z gdb

Możesz spróbować odpalić serwer z Valgrindem.
Mogę spróbować, chociaż kiedyś to robiłem i przy 100+ graczach zalogowanych na serwerze gry jest to ciężkie do wykonania bo będą mocne lagi. Natomiast na serwerze testowym gdy będe sam to może nic nie wykazać.

Należałoby sprawdzić jak dokładnie wygląda cit i tile->creatures.
Co masz na myśli co mam podać?
P-181592
pekfos
» 2024-09-15 21:38:43
Należałoby sprawdzić jak dokładnie wygląda cit i tile->creatures.
Co masz na myśli co mam podać?
To może zacznijmy od tego. Odpal coredump w gdb i przejdź do wątku i ramki gdzie masz te zmienne widoczne (polecenia thread i frame) i je wypisz. To będzie p cit i p tile->creatures. Podaj wynik, zrób disable pretty-printer i podaj wynik jeszcze raz, przykładowo:
(gdb) p i
$11 = non-dereferenceable iterator for std::vector
(gdb) p x
$12 = std::vector of length 0, capacity 0
(gdb) disable pretty-printer
195 printers disabled
0 of 195 printers enabled
(gdb) p i
$13 = {_M_current = 0x0}
(gdb) p x
$14 = {<std::_Vector_base<int, std::allocator<int> >> = {_M_impl = {<std::allocator<int>> = {<std::__new_allocator<int>> = {<No data fields>}, <No data fields>}, <std::_Vector_base<int, std::allocator<int> >::_Vector_impl_data> = {
        _M_start = 0x0, _M_finish = 0x0, _M_end_of_storage = 0x0}, <No data fields>}}, <No data fields>}

W jaki sposób? bo to jest bt full z gdb
Na start wypisz mapę do której należał iterator na którym program się wywalił. Z pretty printerem, żeby sprawdzić czy jest w stanie w ogóle ją odczytać.

Natomiast na serwerze testowym gdy będe sam to może nic nie wykazać.
Wyniki z Valgrinda mogą wskazać problem nawet jeżeli serwer się nie wywali. Potrzebujesz tylko wywołać zachowanie które ma szansę wywalić serwer, nie musi akurat wywalić serwera.
P-181593
dunno
Temat założony przez niniejszego użytkownika
» 2024-09-16 10:28:54
wlasnie nie wygenerowal mi sie coredump chyba przez to ze mialem ulimit -c na zero, teraz dalem ulimit -c unlimited i jak tylko wystapi ten sam błąd to wróce z odpowiedzią.

Z valgrindem tez sprobuje.

Edit: z jakimi opcjami włączonymi odpalać tego valgrinda?

screen -R valgrind --leak-check=full \
         --show-leak-kinds=all \
         --track-origins=yes \
         --verbose \
         --log-file=valgrind-out.txt \
         ./silnikgry

P-181595
pekfos
» 2024-09-16 16:37:57
Pewnie starczy --track-origins=yes, jak w odpowiedzi na stackoverflow, więc to co podałeś powinno być ok.

Upewnij się też że masz dość miejsca na ten coredump, bo inaczej będzie ucięty. Można skonfigurować to tak by się kompresował w locie przy zapisie na dysku: https://stackoverflow.com/questions/5063295/compressing-the-core-files-during-core-generation. Rozmiar będzie zależeć od użycia pamięci przez proces. Przetestuj działanie zabijając serwer ręcznie przez
killall -11 silnikgry
.
P-181596
dunno
Temat założony przez niniejszego użytkownika
» 2024-09-24 08:14:24
Obstawiam że gdzieś masz wiszące wskaźniki na usunięte obiekty i próbujesz coś na nich robić. Taki dostęp do pamięci nie musi wywołać awarii sam z siebie, ale jak ten obszar został zaalokowany na coś innego to uszkodzisz dane i wywołasz błąd w losowym miejscu.
Wracam z odpowiedzią - Twoje słowa naprowadziły mnie na rozwiązanie problemu - nie mogę jeszcze tego potwierdzić na 100%, ale wszystko na to wskazuje, ponieważ crash nie wystąpił już od czasu jednej ze zmian.

Gracz ma możliwość wywoływania skryptu LUA poprzez pisanie z tzw. NPC (Non Player Creature) jeden z wywoływanych skryptów LUA odwoływał się do elementu tablicy zawartej w tym skrypcie, ale elementu poza zakresem tablicy (co zwracało błąd, ale nie crashowało serwera). W związku z tym, że nie wywoływało to żadnego problemu nie było to naprawiane. Po twoich słowach
Taki dostęp do pamięci nie musi wywołać awarii sam z siebie, ale jak ten obszar został zaalokowany na coś innego to uszkodzisz dane i wywołasz błąd w losowym miejscu.
postanowiłem poprawić ten skrypt LUA, aby nie było możliwości odwołania się do elementu poza zakresem tablicy i wszystko zaczęło działać (do tej pory). 100% pewności nabiorę w dłuższej perspektywie, ale na chwilę obecną wszystko wskazuje na rozwiązanie problemu.
Dzięki.
P-181629
« 1 »
  Strona 1 z 1