działa wołanie metod wirtualnyc

Feb 08, 2009 9 Replies

Witam.



Takie coś:



struct X { virtual void run() { do_something(); }; void start() { run(); ); }



kod glowny:



X x;



x.run(); - dziala x.start(); - nie dziala



Anzalizujac kod krok po kroku w OpenOCD widze, że wolanie run() z wnetrza start() prowadzi prosto pod adres NULL. Tak jak gdyby tablica wirtualna była uszkodzona. Z drugiej strony jednak zawołanie wprost run(); działa. Wygląda więc na to że nie działa wołanie metod wirtualnych z innych metod.



arm-elf-g++ w wersji 3.4.3. RTTI włączone. Cpu AT91SAM7S.



Gdzie szukać przyczyny? Może ktoś już się z tym spotkał? Google pytane pod róznymi hasłami kręci się w okolicy EABI ale żadnych konkretów. Mogę podać wszystko włacznie z kawałkami asm, sam niestety słabo znam asm arm7 żeby zabrać się za analizę.


A te zmienne sa statyczne czy automatyczne?

Masz obiekt kompletny, wiec wywolanie x.run() realizowane jest bezposrednio, bez 'wirtualnosci'. Wywolanie jest wirtualne (poprzez tablice) gdy wywolujesz metode ze wskaznika lub referencji. Wewnatrz start() masz wskaznik this.

Jesli to sa zmienne statyczne to podejrzewalbym linkowanie i inicjalizacje. Kazdy plik .cpp zawiera wygenerowana przez kompilator funkcje inicjalizujaca obiekty globalne (wolajaca konstruktory).

Krzysiek Rudnik

Automatyczne, na stacku.

Wiem, dlatego własnie podałem przykład z ominięciem tablicy wirtualnej żeby wykazać ze w niej jest problem.

Tak, w dodatku funkcja start() prawidłowo dochodzi do miejsca w którym pobierany jest wskaźnik na run. Niestety jest on zerowy co może oznaczać, że nie został zainicjowany. Nie wiem gdzie (i kto) jest odpowiedzialny za prowidłwoe wypełnienie tej vtable. Wydawało mi się że konstruktor, ale jak widać chyba nie.

Nie. To zmienne na stosie. Dokładnie tak jak widać w kodzie.

Wiem, mój startup zawiera kod który wywołuje te konstruktory (fakt - nie pisany przez mnie). Jednak w tym wypadku nie ma mowy o statycznych zmiennych. Ponadto sprawdziłem - obiekt statyczny ma wołany konstruktor wiec tutaj chyba nie ma problemu.

Będę jeszcze próbował gcc w jakiejś nowszej wersji z lini 4.x. Być może to bug.

Kiedys (pare lat juz bedzie) byla dyskusja z Piotrem Wyderskim o roznych przelacznikach do gcc na tej grupie. Sprobuj - a nuz...

Już się bawiłem rtti i okolicami. Cięzko trafić jesli to wina przełacznika sądząc po ich ogromie.

PS. 4.x nie działa również, więc to jakiś problem raczej nie typu bug w gcc.

Moze opcje jakies defaultowo poustawiane? Wywolujesz kompilator z 'palca' i w srodowisku nie masz nic na co on zareaguje?

Jakby to byl blad, to by o tym powinno byc glosno. 3.4.3 nie takie nowe jest.

Hmmm nie wiem o czym mówisz, ale po prostu robie wszystko standardowo może poza -nodefaultlibs dzięki któremu zaoszczędzam na takich features jak fteel i podobnie bardzo istotnych funkcjach na uC. W zasadzie jedyne co jest podejrzane to startup wzięty "z internetu", acz działający we wszystkich aspektach. Mam też FreeRTOS ale go wyłaczyłem i wchodząc na czysto do funkcji main od razu mam taki problem jak niedziałanie wirtualnych wywołań. Ponieważ psuje się od razu w main to podejrzewam że startup czegoś nie ustawia.

Dlatego szukam błedu u siebie. Jest też inna sprawa że jestem być może jedyny na świecie który chce mieć C++ na ARM7...

No i znalazłem. Oczywiście był tam gdzie nie spodziewałem się go znaleźć.

Skrypt linkera nie posiadał 3 linijek:

*(.rodata) *(.rodata*) *(.gnu.linkonce.r.*)

Znalazłem to grzebiąc w asm i zauważając wskaźnik w okolicy konstruktora X który ewidentnie wskazywał w "dziurę" w której nie było żadnych danych. Dodanie tych sekcji "wypełniło" tą dziurę właściwymi strukturami vtable.

Sebastian Bialy pisze:

No to nieźle. Jak do tej pory działały Ci chociażby zwykłe printf'y? Ciągi znaków pisane normalnie w cudzysłowach wpadają właśnie do sekcji .rodata, nie zacząłeś dochodzenia od wypisania czegokolwiek na debugu?

Na razie debugowałem ledami :P

Join the Discussion

Have something to add? Share your thoughts — no account required.

Didn't find your answer?

Ask the community — no account required