AVR gcc .bss .heap i stos

Czy jakieś nieświadome użycie, zadeklarowanie zmiennej lokalnej np. float w funkcji może prowadzić do używania obszaru poniżej stosu i powyżej .bss czyli heap? Z pliku .map niewiele widać.

.bss kończy się 0x733 stos na 0x800 podglądany stack pointer schodzni najniżej do 0x795

Czyli pomiędzy 0x733 a 0x795 jest teoretycznie heap ale wzmianki o tym w pliku map nie ma. No ale stos mi nachodzi czasem na zmienne. Jak zmniejszę bufor[512] o kilkadziesiąt to się uspokaja. Co można zrobić ? Skąd wiadomo czy heap jest używany? I co się dzieje w tym obszarze? Z wyliczeń jest miejsce. Wstawiam pułapki w różne miejsca kodu i czytam ile wynosi aktualnie SP i nie ma siły, nie spotykają się. A jednak się kwasi.

.bss .... ....

0x008005f3 RXVAL

0x008005f5 V_TEST

0x008005f7 PROVIDE (__bss_end, .)

0x00006d76 __data_load_start = LOADADDR (.data)

0x00006d76 __data_load_end = (__data_load_start + SIZEOF (.data))

.noinit 0x008005f7 0x13d

0x008005f7 PROVIDE (__noinit_start, .)

*(.noinit*)

.noinit 0x008005f7 0x13d main.o

0x008005f7 my_bufer

0x00800733 my_noinit

0x00800734 PROVIDE (__noinit_end, .)

0x00800734 _end = .

0x00800734 PROVIDE (__heap_start, .)

.eeprom 0x00810000 0x0

*(.eeprom*)

0x00810000 __eeprom_end = .

Reply to
Profesor
Loading thread data ...

Te zmienne będą alokowane na stosie i na bieżąco zwalniane, więc nie.

W .map są tylko statyczne rzeczy.

Wstaw pułapki przy zapisie do pamięci. Można też postawić pułapki na fragmentach kodu (wywołania funkcji) i drogą eliminacji dojść, która bruździ (w podglądzie pamięci widać, które obszary zostały zmienione). Może to niekoniecznie stos, a np. wskaźniki. Poza tym jeszcze są przerwania. Miałem kiedyś ten sam problem i się nie udało dojść do źródła, a najgorsze było to, że potrafiło poprawnie działać przez kilkanaście godzin. Skończyło się na zmniejszeniu zapotrzebowania na RAM. Tu chyba winna była zewnętrzna dość duża biblioteka (CanFestival).

Reply to
shg

  1. Przydzielenie jakiegos obszaru pamięci na stos nie oznacza iż przekroczenia jego rozmiaru nie nastapi (chyba, że w prologu wywoływanej funkcji jest kontrolowana granica stosu).
  2. Typowa sytuacja dla embedded : wywoływanie funkcji rekurencyjnie szybko spowoduje przekroczenie stosu. Alokowanie agregatów na stosie, np. tablic lub głebokie drzewo wywołań funkcji (odkładanie kontekstu na stosie) spowoduje przekroczenie stosu.
  3. Kompilator sie nie myli. Wszystkie zmienne statyczne znajdą sie w odpowienich sekcjach tj. .bbs lub .data a automatyczne na stosie. Przyczyna opisywanego powyżej stanu rzeczy jest zwykle przekroczenie stosu (patrz punkt 2), "urwany" wskażnik itp. (...)

Nie wiem jak w Twoim przypadku ale widziałem taka implementacje : adres stosu był przypisany w skrypcie lnikera do końca pamięci i obszar między końsem bss-ów a końcem RAM był stosem. I tu nastepował wielkie ździwienie iz program sie wywraca a po zmniejszeniu jakis tablic działa. Przecież mniejszy rozmiar na dane to wiekszy stos.

Oszacować niezbedny rozmiar stosu, np. tak (przykład dla architektury ARM) :

// A minimal, optimized stack frame, rounded up - no autos #define CYGNUM_HAL_STACK_FRAME_SIZE (4 * 20)

// Stack needed for a context switch: this is implicit in the estimate for // interrupts so not explicitly used below: #define CYGNUM_HAL_STACK_CONTEXT_SIZE (4 * 20)

// Interrupt + call to ISR, interrupt_end() and the DSR #define CYGNUM_HAL_STACK_INTERRUPT_SIZE \ ((4 * 20) + 2 * CYGNUM_HAL_STACK_FRAME_SIZE)

// Space for the maximum number of nested interrupts, plus room to call functions #define CYGNUM_HAL_MAX_INTERRUPT_NESTING 4

#define CYGNUM_HAL_STACK_SIZE_MINIMUM \ (CYGNUM_HAL_MAX_INTERRUPT_NESTING * CYGNUM_HAL_STACK_INTERRUPT_SIZE

  • \ 2 * CYGNUM_HAL_STACK_FRAME_SIZE)

#define CYGNUM_HAL_STACK_SIZE_TYPICAL \ (CYGNUM_HAL_STACK_SIZE_MINIMUM + \ 16 * CYGNUM_HAL_STACK_FRAME_SIZE)

Należy expicite wywołać funkcje typu *alloc() lub impicite przez uzycie bibliteki wymagającej dynamicznej alokacji pamięci.

Alokator rezerwuje porcje pamięci i zwraca wskaźnik do niej.

nie ma siły, nie spotykają się. A jednak się kwasi. Nie tak. Stos oraz obszar ponizej (jesli nic tam nie ma) nalezy zainicjować wzorcem typu 0xaa55aa55 a nastepnie sprawdzić czy rzeczony wzorzec nie został całkowicie zamazany zmiennymi - podczas normalnej pracy odkładane zmienne NIGDY nie powinny przekroczyc dolnej granicy stosu.

Reply to
Nijak

Napisałeś dużo ciekawych rzeczy ale powiedz mi skąd mam wiedzieć czy nie używam bibliteki wymagającej dynamicznej alokacji pamięci ? Używam zmiennego przecinka, memcpy, memcmp. Alloców expicitenie używam, niczego takiego co trzeba by później zwalniać. Nie wiem co libc czy libm wyprawia. Do czasu aż był ram nie zastanawiałem się nad tym :-)

Teraz troszkę wywaliłem, użyłem też -mrelax i troszkę stos mniej zajmuje bo branches relaxation. Jednak zamiana tych call na rcall przy nested callach pomogło. Teraz sie nie wali. Ale to walenie się było takie subtelnie perfidne :-) Nikt tego nie zauważył :-)

Reply to
Profesor

To sa podstawy.

dynamicznej alokacji pamięci ? Z dokumentacji oraz zrodel.

(..)

Jak wyzej.

Chyba raczej zmniejszenie rozmiaru kodu : -mrelax Enable linker relaxation. Linker relaxation is a process whereby the linker will attempt to reduce the size of a program by finding shorter versions of various instructions. Disabled by default.

Reply to
Nijak

Można też poszukać symboli z grupy .*brk.* czy po prostu malloc.

Reply to
Michoo

Użytkownik "Profesor" napisał w wiadomości grup

No bo to dynamicznie uzywane. Zobacz opcje kompilatora - byc moze da sie wlaczyc kontrole stosu .. ale to dziala tylko w normalnych funkcjach, a jeszcze sa przerwania.

Na gccavr sie nie znam, ale w C czesto wlasnie heap zapelnia z jednej strony, a stos z drugiej.

Moze jakis maxmem da sie ustawic i moze jakas funkcja grzecznie zglosi ze pamieci nie moze zaalokowac.

Jeszcze mozesz ten obszar wypelnic jakas stala zawartoscia, a po przebiegu programu zobaczyc w jakim obszarze zawartosc pozostala nienaruszona.

J.

Reply to
J.F

Już wiadomo. Stos był od dawien dawna ustawiony na 0x800 zamiast na 0x85F :-) Brakowało mi tych ~100 bajtów :-)

Reply to
Profesor

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.