Zrobione, sam zresztą powinienem był uważniej rzucić okiem.
Co do samego błędu, na którym utknąłeś, to nie bardzo mam pomysł. Sieć coś dziwnie działa. Zastanawiające o tyle, że Skoruppa przez ten etap przebrnął akurat dość bezboleśnie, więc to raczej nie problem stricte związany z GCC.
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)
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.
/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
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
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…
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.