Naprawiłem Trzeba było dodać flagę _WIN32_WINNT <- sam boost asio o to krzyczał
Wszystkie mapy ładują się poprawnie, wiec nie ma tego problemu który występuje u Skoruppa.
Naprawiłem Trzeba było dodać flagę _WIN32_WINNT <- sam boost asio o to krzyczał
Wszystkie mapy ładują się poprawnie, wiec nie ma tego problemu który występuje u Skoruppa.
Pierwszy błąd prawie na 100% powoduję polska wersja Drugi pewnie powoduję brak AI bo wstyd się przyznać ale nie skompilowałem. Dikamilo: jak kompilujesz AI? (tak, po prostu mi nie wychodzi :P)
Ja importowałem projekt Visuala i dolinkowałem mu liba VCMI, dodatkowo takie #defines:
WIN32
_WINDOWS
_USRDLL
GENIUS_EXPORTS
Mam jeszcze w projekcie podana ścieżkę do include i libs z boosta ale żaden lib nie jest potrzebny
A pliki w projekcie to:
CGeniusAI.h
CGeniusAI.cpp
DLLMain.cpp
A mógłby mi ktoś wygenerować makefile? Bo ja jestem chyba zbyt wielki amator
EDIT:
Czego bym nie próbował to zawsze
Może coś źle robię…
Zaktualizuj źródła tam jest patch który to poprawia, albo zmień (CGeniusAI.h):
void CBattleLogic::PrintBattleAction(const BattleAction &action);
na
void PrintBattleAction(const BattleAction &action);
Zaktualizuj źródła tam jest patch który to poprawia
Tak, dokładnie rewizja 719 (lub nowsza ).
Po tej poprawce już powinno działać.
Gra się crashuje przy zapisywaniu zaraz po tym:
System message from server: Serializing game info...
Czy to odtwarzalne? Czy zachodzi na wszystkich mapach?
Spróbuj zdebugować sewer, bo wpis w logu jest mało pomocny (serializacja informacji o grze, to dość sporo pracy).
Czy to odtwarzalne? Czy zachodzi na wszystkich mapach?
Spróbuj zdebugować sewer, bo wpis w logu jest mało pomocny (serializacja informacji o grze, to dość sporo pracy).
Tak zachodzi na każdej mapie, a co do debugowania, to za bardzo nie wiem jak się za to wziąć, attach to PID nie bardzo działa, frezuje całą aplikacje, a z miejsca tego nie zrobię bo serwer jest przecież uruchamiany z poziomu klienta.
Podczas kompilacji GeniusAI
/usr/lib/gcc/i486-linux-gnu/4.3.3/../../../../lib/crt1.o: In function `_start':
/build/buildd/glibc-2.9/csu/../sysdeps/i386/elf/start.S:115: undefined reference to `main'
collect2: ld returned 1 exit status
nie wiem czy tu mój błąd czy z coś innego.
Wydaje mi się że nie kompilujesz tego jako lib.
===
Co jak co ale debbugera to ja obsługiwać nie potrafię Tutaj log z crasha przy zapisie gry:
E:\Install\Heroes3>gdb.exe VCMI_server.exe 1280
GNU gdb 6.3
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i686-pc-mingw32"...
Attaching to program `E:\Install\Heroes3/VCMI_server.exe', process 1280
[Switching to thread 1280.0x560]
(gdb) c
Continuing.
Program received signal SIGSEGV, Segmentation fault.
[Switching to thread 1280.0x224]
0x00486c38 in std::string::length () at iostream:77
77 static ios_base::Init __ioinit;
(gdb) bt
#0 0x00486c38 in std::string::length () at iostream:77
#1 0x00455aef in COSer<CSaveFile>::saveSerializable (this=0x162f87c,
data=@0xd990f4) at Connection.h:275
#2 0x0044298c in SaveSerializable<CSaveFile, std::string>::invoke (
s=@0x162f87c, data=@0xd990f4) at Connection.h:69
#3 0x00459122 in COSer<CSaveFile>::save<std::string> (this=0x162f87c,
data=@0xd990f4) at Connection.h:240
#4 0x0045c296 in COSer<CSaveFile>::operator<< <std::string> (this=0x162f87c,
t=@0xd990f4) at Connection.h:185
#5 0x0045a4a2 in COSer<CSaveFile>::operator&<std::string> (this=0x162f87c,
t=@0xd990f4) at Connection.h:192
#6 0x004369dd in PlayerInfo::serialize<COSer<CSaveFile> > (this=0xd990d4,
h=@0x162f87c, version=63) at map.h:129
#7 0x00455de0 in COSer<CSaveFile>::saveSerializable<PlayerInfo> (
this=0x162f87c, data=@0xd990d4) at Connection.h:245
#8 0x00442388 in SaveSerializable<CSaveFile, PlayerInfo>::invoke (
s=@0x162f87c, data=@0xd990d4) at Connection.h:69
#9 0x004581f2 in COSer<CSaveFile>::save<PlayerInfo> (this=0x162f87c,
data=@0xd990d4) at Connection.h:240
#10 0x0045ae56 in COSer<CSaveFile>::operator<< <PlayerInfo> (this=0x162f87c,
t=@0xd990d4) at Connection.h:185
#11 0x00455db0 in COSer<CSaveFile>::saveSerializable<PlayerInfo> (
this=0x162f87c, data=@0xd141f4) at Connection.h:253
---Type <return> to continue, or q <return> to quit---
#12 0x00442d28 in SaveSerializable<CSaveFile, std::vector<PlayerInfo, std::alloc
ator<PlayerInfo> > >::invoke (s=@0x162f87c, data=@0xd141f4) at Connection.h:69
#13 0x004595c6 in COSer<CSaveFile>::save<std::vector<PlayerInfo, std::allocator<
PlayerInfo> > > (this=0x162f87c, data=@0xd141f4) at Connection.h:240
#14 0x0045c8c6 in COSer<CSaveFile>::operator<< <std::vector<PlayerInfo, std::all
ocator<PlayerInfo> > > (this=0x162f87c, t=@0xd141f4) at Connection.h:185
#15 0x0045a802 in COSer<CSaveFile>::operator&<std::vector<PlayerInfo, std::alloc
ator<PlayerInfo> > > (this=0x162f87c, t=@0xd141f4) at Connection.h:192
#16 0x00435e61 in CMapHeader::serialize<COSer<CSaveFile> > (this=0xd14198,
h=@0x162f87c, Version=63) at map.h:226
#17 0x00455ca8 in COSer<CSaveFile>::saveSerializable<CMapHeader> (
this=0x162f87c, data=@0xd14198) at Connection.h:245
#18 0x00442350 in SaveSerializable<CSaveFile, CMapHeader>::invoke (
s=@0x162f87c, data=@0xd14198) at Connection.h:69
#19 0x00458186 in COSer<CSaveFile>::save<CMapHeader> (this=0x162f87c,
data=@0xd14198) at Connection.h:240
#20 0x0045adc6 in COSer<CSaveFile>::operator<< <CMapHeader> (this=0x162f87c,
t=@0xd14198) at Connection.h:185
#21 0x0040dbdd in CGameHandler::handleConnection (this=0x22fb54, players=
{_M_t = {_M_impl = {<std::allocator<std::_Rb_tree_node<int> >> = {<__g
nu_cxx::new_allocator<std::_Rb_tree_node<int> >> = {<No data fields>}, <No data
fields>}, _M_key_compare = {<> = {<No data fields>}, <No data fields>}, _M_heade
r = {_M_color = 14095560, _M_parent = 0xd91e80, _M_left = 0x0, _M_right = 0x7c91
---Type <return> to continue, or q <return> to quit---
0098}, _M_node_count = 2009244481}}}, c=@0xd714c8) at CGameHandler.cpp:460
#22 0x00483091 in boost::_mfi::mf2<void, CGameHandler, std::set<int, std::less<i
nt>, std::allocator<int> >, CConnection&>::operator() (this=0x24b050,
p=0x22fb54, a1=
{_M_t = {_M_impl = {<std::allocator<std::_Rb_tree_node<int> >> = {<__g
nu_cxx::new_allocator<std::_Rb_tree_node<int> >> = {<No data fields>}, <No data
fields>}, _M_key_compare = {<> = {<No data fields>}, <No data fields>}, _M_heade
r = {_M_color = 14095560, _M_parent = 0xd87748, _M_left = 0xd91e80, _M_right = 0
xd714c8}, _M_node_count = 2292564}}}, a2=@0xd714c8) at mem_fn_template.hpp:274
#23 0x00461e8c in boost::_bi::list3<boost::_bi::value<CGameHandler*>, boost::_bi
::value<std::set<int, std::less<int>, std::allocator<int> > >, boost::reference_
wrapper<CConnection> >::operator()<boost::_mfi::mf2<void, CGameHandler, std::set
<int, std::less<int>, std::allocator<int> >, CConnection&>, boost::_bi::list0>
(this=0x24b058, f=@0x24b050, a=@0x162ff0f) at bind.hpp:371
#24 0x00462d1d in boost::_bi::bind_t<void, boost::_mfi::mf2<void, CGameHandler,
std::set<int, std::less<int>, std::allocator<int> >, CConnection&>, boost::_bi::
list3<boost::_bi::value<CGameHandler*>, boost::_bi::value<std::set<int, std::les
s<int>, std::allocator<int> > >, boost::reference_wrapper<CConnection> > >::oper
ator() (this=0x24b050) at bind_template.hpp:20
#25 0x0046e294 in boost::detail::thread_data<boost::_bi::bind_t<void, boost::_mf
i::mf2<void, CGameHandler, std::set<int, std::less<int>, std::allocator<int> >,
CConnection&>, boost::_bi::list3<boost::_bi::value<CGameHandler*>, boost::_bi::v
alue<std::set<int, std::less<int>, std::allocator<int> > >, boost::reference_wra
Cannot access memory at address 0x1630000
Jesteś wielki a mi wróciła wiara w to, że jednak potrafię kompilować wystarczyło dodać -shared. Zaraz przetestuję i zobaczę
dikamilo, nie mam pojęcia czemu to wywołanie length() na stringu sypie. Gdyby to jeszcze był string pod jakimś wskaźnikiem, to by można spekulować, czy jest on poprawny, ale tak… wskaźnik będący normalnym polem klasy nie powinien robić problemów, zwłaszcza jeśli kilka poprzednich pól się zserializowało, więc okoliczna pamięc jest dostępna.
Problem może być z runtimem (runtime libraries - biblioteki uruchomieniowe). Nie wiem jak jest to zorganizowane w MinGW-ie, ale Visual posiada kilka wariantów runtime’u i wybiera się odpowiedni. Są bodajże wersje statycznie włączane do aplikacji jedno- i wielowątkowych oraz wersja w osobnej dll-ce. VCMI musi mieć runtime w dll-ce. W innym wypadku dochodzi do błędów, ponieważ zarówno do liba jak i klienta włączany jest runtime i otrzymujemy dwa runtime’y niekompatybilne ze sobą (dwie osobne sterty, nieprzenośne wskaźniki itp).
Przyjrzałbym się, jak to wygląda w MinGW-u.
EDIT:
Problem można by w sumie obejść jeszcze inaczej - pozbyć się liba jako autonomicznej części. Można by go albo ręcznie wepchać do klienta i serwera (po prostu modyfikując ich projekty, dodając pliki z liba), albo zbudować jako bibliotekę statyczną i ją potem włączać (chyba też zadziała?).
O ile to jest faktycznie problem z runtimem.
Pobawiłem się trochę debuggerem, ogólnie to sypie się przy serializowaniu zmiennej mainHeroName z PlayerInfo, w trakcie debugger pokazuje taką zawartość:
(gdb) display mainHeroName
1: this->mainHeroName = {static npos = 4294967295,
_M_dataplus = {<std::allocator<char>> = {<__gnu_cxx::new_allocator<char>> = {<
No data fields>}, <No data fields>}, _M_p = 0xd8ae0c ""}}
Próbowałem zmienić w locie zawartość tej zmiennej to wyskakuje takie coś:
(gdb) set mainHeroName="oko"
Invalid cast.
Można natomiast zmienić na jakąś liczbę, ale przecież ta zmienna jest stringiem ? Ogólnie to problem z tą zmienną był chyba również przy błędach z mapami.
Ja tam będę obstawał, że to może być problem z runtimem, albo coś innego, niekonwencjonalnego.
Ten string jest w 3 miejscach używany. Gdy powstaje, przy wyborze mapy (MapSel::select - sprawdzamy jego długość i ew. kopiujemy do ustawień gracz) i w serializacji.
Jeżeli podczas wyboru mapy wywołanie length() na tym stringu nie powodowało problemów i potem nie był on ruszany, to w żaden konwencjonalny sposób nie miał prawa się popsuć i sypać później, przy serializacji. Albo runtime psuje, albo jest przez coś nadpisywany - ale w to drugie nie bardzo wierzę, jeste nad nim kilka raczej niegroźnych pól.
Co prawda po stronie serwera wyboru mapy i nie ma i ten string nie jest w ogóle ruszany, ale powstaje wskutek identycznej procedury, więc nie ma możliwości, by był inny.
Co do zawartości stringa wg debuggera, to generalnie dlatego nie lubię gdb, że nie bardzo wiadomo co jest w kontenerach STL-owskich w tych jego podglądach.
Czy to _M_p = 0xd8ae0c “” oznacza, że pod adresem 0xd8ae0c jest NULL (to by wskazywało na pusty string, rozsądnie zakładając, że _M_p to wskaźnik na początek tekstu). No ale nawet pusty string nie ma prawa sypać (length() powinien wtedy grzecznie zwrócić 0).
Teza o runtime tym bardziej uzasadniona, że przy crashu jeszcze są jakieś awantury o "static ios_base::Init __ioinit; ". Choć na moje oko, to w takim układzie toto powinno sypać inaczej…
Choć do końca nic nie potrafię tu powiedzieć…
Dziwne problemy.
Może sam powinienem w wolnej chwili zacisnąć zęby i spróbować skompilować VCMI MinGW-em…
Próbowałem zmienić w locie zawartość tej zmiennej to wyskakuje takie coś:
Można natomiast zmienić na jakąś liczbę, ale przecież ta zmienna jest stringiem ?
Nie, to nie takie proste. Problem jest takie, że w C/C++ nie masz takiego typu jak string. std::string jest tak naprawdę klasą opakowującą wskaźnik na ciąg bajtów (znaków), długość i jakieś inne wewnętrzne sprawy implementacji. (debugger zresztą Ci wyświetla z czego tak naprawdę ten string się składa)
Z poziomu debuggera nie da się do czegoś takiego łatwo przypisać innej wartości.
EDIT:
A tak z ciekawości - jeśli byś wykomentował serializację tych imion (map.h l.130) bohaterów, to co się stanie? Jakiś inny string sypnie, czy przejdzie?
Po wywaleniu mainHeroName z (template void serialize(Handler &h, const int version)) : 127, nie wywala żadnego błędu, gra się zapisuje i nawet poprawnie ładuje.
Co do rutime’a mam ustawione standardowo na dynamic (DLL), przy zmianie na static sypało błędami, nie odnajdowało referencji do funkcji, myślę że dużo by trzeba było zmieniać w kodzie aby to zadziałało tak jak pisałeś w poprzednim poście.
Co do rutime’a mam ustawione standardowo na dynamic (DLL), przy zmianie na static sypało błędami, nie odnajdowało referencji do funkcji, myślę że dużo by trzeba było zmieniać w kodzie aby to zadziałało tak jak pisałeś w poprzednim poście.
Ma być właśnie na dynamic dll. Czyli dobrze jest, mój trop był błędny.
Cóż, skoro zakomentowanie serializacji tamtego stringu cudownie naprawiło sytuację, to możesz go sobie trzymać zakomentowany. Tak naprawdę nie jest on jeszcze nigdzie wykrozystywany - to imię głównego bohatera, które powinno być (nie jest) wyświetlane w oknie zaawansowanych opcji w pregamie.
Ale nadal nie mam pojęcia, dlaczego to sypało. Ktoś ma jakiś pomysł?
Ale nadal nie mam pojęcia, dlaczego to sypało. Ktoś ma jakiś pomysł?
ja mam!
problem z wartością wskaźnika (string jest wskaźnikiem (char*) )
źle ustawiony wskaźnik powoduje niedozwoloną operację w length, z powodu zabezpieczeń pamięci w linuksie (brak sprawdzania warunków krytycznych), gdb sprawdza co i jak i zamiast się sypnąć daje NULLa (nie widzi nic sensownego)
błędy mogą wystąpić przez złę ustawienie wskaźnika, ustawienie w runtime wartości do (const (char )) (a może to było ((const char)) ?) niezgodność typów wskaźnikowych (np. podstawienie zvoidowanego wskaźnika nie do stringu lub przypisanie stałej liczby do wskaźnika) lub problem z samym length (sypie na static cośtam, zmienne wewnętrzne źle się ustawiają (zwłaszcza wskaźniki brrrrrr! - ten sam problem co wyżej) )
również problemem może być zapis do pamięci read-only, przypisanie danych do zawartości wskaźnika NULL zwróconego przez funkcję zarządzania pamięci (np. alloc), wyjście poza dozwolony zakres pamięci (pamięć bez praw do czytania przez proces)
proponuje update bibliotek (zwłaszcza tych domyślnych wraz z kompilatorem) i sprawdzenie czy dalej się sypie
ewentualnie w kodzie możesz wstawić globalny (char ) z wstawionym stringiem np “test string” i za pomocą gdb przypisać wątpliwemu wskaźnikowi (char) wstawić wartość tego globalnego wskaźnika (równe wskaźniki pokazują na to samo, co nie?)
(string jest wskaźnikiem (char*))
W bardzo, bardzo dużym przybliżeniu. To jest klasa i ma jeszcze zazwyczej kilka innych pól oprócz tego wskaźnika.
źle ustawiony wskaźnik powoduje niedozwoloną operację w length, z powodu zabezpieczeń pamięci w linuksie (brak sprawdzania warunków krytycznych), gdb sprawdza co i jak i zamiast się sypnąć daje NULLa (nie widzi nic sensownego)
Windowsy też sprawdzają pamięć a na nich nie sypie. Poza tym skoro gdb może odczytać wskaźnik, to prawdopodobnie length też powinno móc (gdy gdb nie może się dostać do pamięci, to daje “Cannot access memory at address”, a nie udaje, że tam jest NULL).
błędy mogą wystąpić przez złę ustawienie wskaźnika, ustawienie w runtime wartości do (const (char )) (a może to było ((const char)) ?) niezgodność typów wskaźnikowych (np. podstawienie zvoidowanego wskaźnika nie do stringu lub przypisanie stałej liczby do wskaźnika) lub problem z samym length (sypie na static cośtam, zmienne wewnętrzne źle się ustawiają (zwłaszcza wskaźniki brrrrrr! - ten sam problem co wyżej) )
Jakie const char * i co to za nawiasy? Jaka niezgodność typów? Jakie zmienne wewnętrzne? Możesz składniej i bardziej po polsku, bo to mi wygląda na bełkot?
również problemem może być zapis do pamięci read-only, przypisanie danych do zawartości wskaźnika NULL zwróconego przez funkcję zarządzania pamięci (np. alloc), wyjście poza dozwolony zakres pamięci (pamięć bez praw do czytania przez proces)
Wymieniasz wszystkie możliwe przyczyny sypania się programu, jakie znasz? My też je znamy, i jeszcze trochę innych. Lepiej napisz, co to na pewno nie jest, bardziej pomoże (bo na napisanie przez ciebie co to na pewno jest nie liczę).
proponuje update bibliotek (zwłaszcza tych domyślnych wraz z kompilatorem) i sprawdzenie czy dalej się sypie
Wiem, że nie zawsze można ufać bibliotekom standardowym, szczególnie z projrktów otwartych, ale bez przesady. Tego typu błędy w stringach są praktycznie wykluczone, kiedyś możnaby myśleć, że nie zrobili zabezpieczeń dla jednoczesnego korzystania ze stringa przez wiele wątków, ale na moje oko ani to ten przypadek, ani te czasy.
ewentualnie w kodzie możesz wstawić globalny (char ) z wstawionym stringiem np “test string” i za pomocą gdb przypisać wątpliwemu wskaźnikowi (char) wstawić wartość tego globalnego wskaźnika (równe wskaźniki pokazują na to samo, co nie?)
Dobra, a skąd wiesz że to nie psuje kompletnie stringa i nic z nim nie da się robić za pomocą zaimplementowanych metod? Nie wydaje mi się, żeby to mogło do czegokolwiek prowadzić.
Moim zdaniem bardziej interesujące jest, czemu wierzchołek stosu jest taki jaki jest (0x00486c38 in std::string::length () at iostream:77), iostream:77 ma niewiele wspólnego z std::string::length ().
hey guys!
i also tried to compile vcmi on linux and after initial fail i tried to search for others who strive for this goal.
so after skimming through a google translate of the thread there seems to be some achievements in this regard.
could you in short summarize the steps i have to take to make it initially compile for now? it seems the issues mentioned here are not yet in svn?
after a successful compile i can do some gdb debugging.
and sorry for intruding into your polish section - i thought that maybe this issue gets more attention when it is discussed in english
Hosting provided by DigitalOcean