www.mikrocontroller.net

Forum: Compiler & IDEs Optimale Stacksize bestimmen


Autor: Christian J. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

die User Stacksize wird bei der Rowley Umgebung zu Anfang fix 
eingestellt.  Ebenso FIQ und IRQ Größen.

Fragt sich nur: Wie gut liegt man mit seiner Schätzung? Egal wie ich den 
Wert verändere, der Compiler und auchn Linker meckert nicht.

Wie kann man denn die Größe so bestimmen, dass sie eben optimal passt 
und man keinen wertvollen RAM verschenkt? Beim PIC Compiler rechnet der 
es aus der maximalen Verschachtelungstiefe aus, beim GCC weiss ich nicht 
wie das geht.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Christian J. schrieb:

> Fragt sich nur: Wie gut liegt man mit seiner Schätzung? Egal wie ich den
> Wert verändere, der Compiler und auchn Linker meckert nicht.

Wundert mich wenig.
Wenn der Stack zu klein ist, merkst du das erst zur Laufzeit. Und das 
auch nur wenn in deinem Programm plötzlich seltsame Dinge passieren bzw. 
dein Compiler bei jedem Funktionsaufruf Code einbaut, der die Stackgröße 
überwacht und Alarm schlägt.

> Wie kann man denn die Größe so bestimmen, dass sie eben optimal passt

Gegen das Wort 'optimal' hab ich ein Aversion entwickelt.

> und man keinen wertvollen RAM verschenkt? Beim PIC Compiler rechnet der
> es aus der maximalen Verschachtelungstiefe aus, beim GCC weiss ich nicht
> wie das geht.

Die benötigte Stacksize ist im Allgemeinen nicht per Programm 
bestimmbar. Das wäre eine Variation des Turingschen Halteproblems und 
ist daher prinzipiell nicht möglich. Was nicht heißt, das es für 
einzelne Programme nicht gehen mag. Nur ist es eben nicht für jedes 
beliebige Programm möglich die benötigte Stacksize durch Betrachten des 
Source Codes zu bestimmen.

Autor: Christian J. (elektroniker68)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

aber irgendwie muss man doch die optimale Size bestimmen können. Wenn 
das der CCS Compiler kann, dann können das doch auch andere. Sobald die 
Abhängigkeiten bekannt sich lässt sich das ausrechnen.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Christian J. schrieb:
> Hallo,
>
> aber irgendwie muss man doch die optimale Size bestimmen können.
#include <stdio.h>

unsigned int foo( unsigned int j )
{
  if( j == 0 )
    return 1;

  return foo( j - 1 );
}

int main()
{
  unsigned int k;

  scanf( "%u", &k );
  printf( "%u\n", foo( k ) );
}

Wie soll ein Linker daraus die "optimiale" Stacksize bestimmen können, 
wenn er nicht weiß, was der Benutzer eingeben wird?
(Der Compiler kann sowas prinzipbedingt nicht bestimmen, da er im 
Regelfall das komplette Programm nie zu Gesicht bekommt)

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Wenn das der CCS Compiler kann, dann können das doch auch andere.
Auch er kann es nicht, was macht er wohl bei


void test( int a ) {
   char dummy[20];
   sprintf(dummy, "%d", a);
   for( int i = a; i < 10 + strlen( dummy ); ++i ) {
      test( i+1 );
   }
}

main() {
  test(0);
}

na wieviel stack braucht du wohl, ich glaube kaum das der Compliler das 
ermitteln kann?

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Christian J. schrieb:
> Wie kann man denn die Größe so bestimmen, dass sie eben optimal passt
> und man keinen wertvollen RAM verschenkt?

Dazu muß man in die Internas des Compilers gehen.

Es gibt Compiler, die brauchen keinerlei Einstellungen. Z.B. beim 
AVR-GCC kommen unten die globalen Variablen, danach dann Malloc und der 
Stack wächst vom Ende des SRAM nach unten.
Wenn es dann kracht, hilft keine Einstellung, dann wurde zuviel Speicher 
belegt und das Malloc rennt in den Stack rein bzw. umgekehrt.

Das manche Compiler aber mehrere Stacks benötigen, dient wohl der 
Vorbereitung von Multitasking.

Da hilft wohl nur eine Analyse zur Laufzeit. Man füllt allen unbenutzten 
SRAM mit einem Muster, z.B. 0x77 und testet nach ner Weile, wieviel 
davon in den einzelnen Stacks noch übrig ist.


Peter

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Peter Dannegger schrieb:

> Das manche Compiler aber mehrere Stacks benötigen, dient wohl der
> Vorbereitung von Multitasking.

Und an der Architektur der AVRs. Da AVR keinen atomaren Update von SP 
ermöglicht, tut sich ein Compiler etwas leichter, wenn der Stack für die 
lokalen Variablen vom Return-Stack getrennt wird. Einer dieser beiden 
Stacks ist dann fix.

Autor: kjk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hallo ,

ich mache das so, das ich erst den speicher voll schreibe, um dann zu 
testen wieviel verändert wurde.
so kann man ungefähr abschätzen wieviel man braucht.

an pregnanten stellen testmymem("xyz"); aufrufen.

im main file:

#ifndef FLASH_RELEASE
void testmymem(char *loc){
  unsigned int* lHeapPtr = (unsigned int*) &__heap_start__;
  while (lHeapPtr)
  {
    DBG("\nheap space left %d :%s", *(lHeapPtr + 1), loc);
    lHeapPtr = (unsigned int*) *lHeapPtr;
  }

  unsigned long stack_used, irq_stack_used, fiq_stack_used, 
svc_stack_used, und_stack_used, abt_stack_used, bss_used;
  stack_used = get_stack_used(&__stack_start__, &__stack_end__);
  DBG("\nstack_used %d :%s", stack_used, loc);
  irq_stack_used = get_stack_used(&__stack_irq_start__, 
&__stack_irq_end__);
  DBG("\nirq_stack_used %d :%s", irq_stack_used, loc);
  fiq_stack_used = get_stack_used(&__stack_fiq_start__, 
&__stack_fiq_end__);
  DBG("\nfiq_stack_used %d :%s", fiq_stack_used, loc);
  svc_stack_used = get_stack_used(&__stack_svc_start__, 
&__stack_svc_end__);
  DBG("\nsvc_stack_used %d :%s", svc_stack_used, loc);
  und_stack_used = get_stack_used(&__stack_und_start__, 
&__stack_und_end__);
  DBG("\nund_stack_used %d :%s", und_stack_used, loc);
  abt_stack_used = get_stack_used(&__stack_abt_start__, 
&__stack_abt_end__);
  DBG("\nstack_stack_used %d :%s", abt_stack_used, loc);
  bss_used = get_bss_used(&__bss_start__, &__bss_end__);
  DBG("\nbss_used %d :%s", bss_used, loc);
}
#endif

im crt0.S file:
#ifdef INITIALIZE_STACKS
  mov r2, #0xCC
  ldr r0, =__stack_und_start__
  ldr r1, =__stack_und_end__
  bl memory_set
  ldr r0, =__stack_abt_start__
  ldr r1, =__stack_abt_end__
  bl memory_set
  ldr r0, =__stack_irq_start__
  ldr r1, =__stack_irq_end__
  bl memory_set
  ldr r0, =__stack_fiq_start__
  ldr r1, =__stack_fiq_end__
  bl memory_set
  ldr r0, =__stack_svc_start__
  ldr r1, =__stack_svc_end__
  bl memory_set
  ldr r0, =__stack_start__
  ldr r1, =__stack_end__
  bl memory_set
#endif

Autor: Mark .. (mork)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
A. K wrote

> Und an der Architektur der AVRs. Da AVR keinen atomaren Update von SP
> ermöglicht, tut sich ein Compiler etwas leichter, wenn der Stack für die
> lokalen Variablen vom Return-Stack getrennt wird. Einer dieser beiden
> Stacks ist dann fix.

Auch beim AVR ist ein atomarer Zugriff auf SP möglich, indem man die 
Interrupts sperrt und danach wieder freigibt. Genau das macht auch der 
avr-gcc, wenn er Platz für lokale Variablen auf dem Stack reserviert. 
Einen weiteren (Software-)Stack benutzt avr-gcc nicht.

MfG Mark

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.