RTV forum PL | NewsGroups PL

Analiza przekroczenia stosu i obszaru heap w programach AVR GCC - problemy i rozwiązania

AVR gcc .bss .heap i stos

NOWY TEMAT

elektroda NewsGroups Forum Index - Elektronika Polska - Analiza przekroczenia stosu i obszaru heap w programach AVR GCC - problemy i rozwiązania

Profesor
Guest

Thu Jun 21, 2012 6:59 am   



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 = .

shg
Guest

Thu Jun 21, 2012 10:16 am   



On Jun 21, 8:59 am, "Profesor" <p...@fi.bus> wrote:
Quote:
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?
Te zmienne będą alokowane na stosie i na bieżąco zwalniane, więc nie.


Quote:
Czyli pomiędzy 0x733 a 0x795 jest teoretycznie heap ale wzmianki o tym w
pliku map nie ma.
W .map są tylko statyczne rzeczy.



Quote:
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.

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).

Profesor
Guest

Thu Jun 21, 2012 12:45 pm   



"shg" <shogoonn@gmail.com> wrote in message
news:ec31aa09-6884-4893-a272-bba20c5c0827@p27g2000vbl.googlegroups.com...
On Jun 21, 8:59 am, "Profesor" <p...@fi.bus> wrote:

Quote:
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).

Właśnie to zauważyłem . Tak mam. Jak trochę przyoszczędziłem na tablicach -
dosłownie wczoraj- to zaraz mu przeszło. Ale jasnego powodu nie ma.
Przynajmniej jeśli chodzi o wyliczenia i obecność heap. Natomiast heap mi
się pojawia gdy napiszę:

__malloc_margin = 32;

to pojawiają sie w ramie zmienne 3 sztuki 16 bitowe od adresu 0x60
wskazujące na ten margin, początek i koniec heapu.

A internet przepisuje tylko jeden za drugim i nikt nic nie wyjaśnia tylko
kopiują info z libc. Może ktoś ma pojęcie jak ten margin działa i czemu go
nie ma bez zadeklarowania chociaż podobno defaultowy to 32 ??? To jest heap
czy nie ma bez tej deklaracji? Ja niby rozumiem ideę ale gdy nagle wyskoczy
przerwanie mimo marginesu 32 i pusznie 32 rejestry plus jeszcze kilka skoków
to jest szansa, że stos nadpisze heap.

Nijak
Guest

Thu Jun 21, 2012 1:42 pm   



Profesor wrote:

Quote:
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?
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.
(...)


Quote:
No ale stos mi nachodzi czasem na zmienne. Jak zmniejszę bufor[512] o
kilkadziesiąt to się uspokaja.
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.

Quote:
Co można zrobić ?
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)

Quote:
Skąd wiadomo czy heap jest używany?
Należy expicite wywołać funkcje typu *alloc() lub impicite

przez uzycie bibliteki wymagającej dynamicznej alokacji pamięci.

Quote:
I co się dzieje w tym obszarze?
Alokator rezerwuje porcje pamięci i zwraca wskaźnik do niej.


Quote:
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.

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.

Profesor
Guest

Thu Jun 21, 2012 2:05 pm   



"Nijak" <brak@brak.pl> wrote in message news:jrv8c3$d7r$1@inews.gazeta.pl...
Quote:
Profesor wrote:

Skąd wiadomo czy heap jest używany?
Należy expicite wywołać funkcje typu *alloc() lub impicite
przez uzycie bibliteki wymagającej dynamicznej alokacji pamięci.

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 Smile Nikt tego nie zauważył Smile

Nijak
Guest

Thu Jun 21, 2012 4:24 pm   



Profesor wrote:

Quote:
"Nijak" <brak@brak.pl> wrote in message
news:jrv8c3$d7r$1@inews.gazeta.pl...
Profesor wrote:

Skąd wiadomo czy heap jest używany?
Należy expicite wywołać funkcje typu *alloc() lub impicite
przez uzycie bibliteki wymagającej dynamicznej alokacji pamięci.

Napisałeś dużo ciekawych rzeczy
To sa podstawy.


Quote:
ale powiedz mi skąd mam wiedzieć czy nie używam bibliteki wymagającej
dynamicznej alokacji pamięci ?

Z dokumentacji oraz zrodel.

(..)
Quote:
Nie wiem co libc czy libm wyprawia.
Jak wyzej.



Quote:
Teraz troszkę wywaliłem, użyłem też -mrelax i troszkę stos mniej zajmuje
bo branches relaxation.
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.

Michoo
Guest

Fri Jun 22, 2012 12:06 am   



On 21.06.2012 18:24, Nijak wrote:
Quote:
ale powiedz mi skąd mam wiedzieć czy nie używam bibliteki wymagającej
dynamicznej alokacji pamięci ?
Z dokumentacji oraz zrodel.
Można też poszukać symboli z grupy .*brk.* czy po prostu malloc.



--
Pozdrawiam
Michoo

Profesor
Guest

Fri Jun 22, 2012 11:26 am   



No to mam winowajcę Smile
To moja głowa hehe Smile
Z jakiegoś powodu ustawiając procek na 32A on sobie wpisał stos jako 0x800,
a miało być 0x860 Smile mam na myśli ustawienia projektu.
To działało, bo nie miałem takiego ciśnienia na ram jak po ostatnich
zmianach Smile
Chyba my trzeba podać w tym AtmelStudio6 adres przesunięty o rejestry nie ?
REJESTRY + RAM i jeden powyżej.???
Ja wiem jak się to robi w assemblerze i jak sie ustawia ale w tych "IDE"
nigdy nic nie wiadomo Smile

Profesor
Guest

Fri Jun 22, 2012 11:29 am   



Quote:
Ja wiem jak się to robi w assemblerze i jak sie ustawia ale w tych "IDE"
nigdy nic nie wiadomo Smile

.... A właśnie i nikt z Was też tego nie zauważył Smile Nawet to napisałem w 1
poście. 4 dni poszły sobie ale za to wyczyściłem program Smile Zmniejszyłem
zapotrzebowanie na stos o 50 bajtów, tak przy okazji Smile

identyfikator: 20040501
Guest

Fri Jun 22, 2012 2:49 pm   



Zmniejszyłem
Quote:
zapotrzebowanie na stos o 50 bajtów, tak przy okazji Smile

dobre, wyczyściłem program, jak to się robi?

Profesor
Guest

Fri Jun 22, 2012 3:13 pm   



"identyfikator: 20040501" <NOSPAMtestowanije@go2.pl> wrote in message
news:js20mj$rkm$1@node2.news.atman.pl...
Quote:
Zmniejszyłem
zapotrzebowanie na stos o 50 bajtów, tak przy okazji :-)

dobre, wyczyściłem program, jak to się robi?

Przemyślałem zapotrzebowanie na tablice i zmienne i na skoki rekurencyjne.
Teraz stos ustawiony na 0x85F
Tak mi coś brakowało tych 96 bajtów Smile Poprzednie ustawienie 0x800 nie
robiło kłopotu do czasu aż przyrosło kodu Smile

J.F
Guest

Fri Jun 22, 2012 3:33 pm   



Użytkownik "Profesor" napisał w wiadomości grup
Quote:
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?
.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 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.

Quote:
Co można zrobić ? Skąd wiadomo czy heap jest używany? I co się dzieje
w tym obszarze?

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.

Quote:
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.

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



J.

Profesor
Guest

Fri Jun 22, 2012 3:42 pm   



"J.F" <jfox_xnospamx@poczta.onet.pl> wrote in message
news:js239a$6aa$1@inews.gazeta.pl...

Quote:
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.

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

Marcin Wasilewski
Guest

Fri Jun 22, 2012 8:52 pm   



Użytkownik "Profesor" <pro@fi.bus> napisał w wiadomości
news:js1kp4$1eu$1@node1.news.atman.pl...

Quote:
Ja wiem jak się to robi w assemblerze i jak sie ustawia ale w tych "IDE"
nigdy nic nie wiadomo Smile

Wg mnie po wyborze odpowiedniego procka w IDE o ile nic nie
pokombinujesz to stos jest domyślnie ustawiany na wartość RAMEND. Natomiast
jeśli coś ręcznie kombinujesz, to później są skutki.

Profesor
Guest

Fri Jun 22, 2012 9:13 pm   



"Marcin Wasilewski" <jakis@adres.pl> wrote in message
news:js2mmt$qju$1@inews.gazeta.pl...
Quote:
Użytkownik "Profesor" <pro@fi.bus> napisał w wiadomości
news:js1kp4$1eu$1@node1.news.atman.pl...

Ja wiem jak się to robi w assemblerze i jak sie ustawia ale w tych "IDE"
nigdy nic nie wiadomo :-)

Wg mnie po wyborze odpowiedniego procka w IDE o ile nic nie
pokombinujesz to stos jest domyślnie ustawiany na wartość RAMEND.
Natomiast jeśli coś ręcznie kombinujesz, to później są skutki.

Chyba nie.

W AtmelStudio6 jak robisz New project to pole jest puste. W assemblerze
czyta in SPH i in SPL i odkłada out SLH i SPL przez rejestr.
W jednej z poprzednich wersji był stos na 0x800 ale checbox wyłączony i to
pole pokazywało 800h ale szare. Musiało sie coś w między czase stać podczas
importu.
To jest pół przypadek, a pół moje niedopatrzenie. Ale już działa Smile 4 dni
na to straciłem Smile

elektroda NewsGroups Forum Index - Elektronika Polska - Analiza przekroczenia stosu i obszaru heap w programach AVR GCC - problemy i rozwiązania

NOWY TEMAT

Regulamin - Zasady uzytkowania Polityka prywatnosci Kontakt RTV map News map