Normalt att det blir bugg om man anropar funktion i funktion

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
Användarvisningsbild
Al_Bundy
Inlägg: 2889
Blev medlem: 11 september 2012, 23:59:50
Ort: The U.S - Chicago
Kontakt:

Normalt att det blir bugg om man anropar funktion i funktion

Inlägg av Al_Bundy »

Hej!

Jag håller på skriva lite kod och jag är inne i en funktion och funktionen ställer några frågor. Då tänkte jag införa en back-knapp så man kan backa till föregående fråga eller längre.

Men när jag är i funktionen och backa, dvs jag anropar samma funktion som jag är i. Det går bra EN gång. Men nästa gång när jag gör det så blir det bugg i form av att den skriver ej ut allt på skärmen och ibland blir skärmen bara tom. Är detta normalt att det kan "fucka upp" om man anropar samma funktion mer än 2 gånger?

Jag använder ATmega328 med arduino, utan 16 mhz klockan.

P.S Om ni undrar hur det gick med spänningsvarnaren så tänker jag använda en ATtiny45. Vadå? Kostar ju bara 9 kr styck.
Nerre
Inlägg: 27229
Blev medlem: 19 maj 2008, 07:51:04
Ort: Upplands väsby

Re: Normalt att det blir bugg om man anropar funktion i funk

Inlägg av Nerre »

Jag förstår inte vara du pratar om, men du behöver nog läsa på om globala och lokala variabler och framförallt vilket scope som gäller för en variabel.

Jag antar att det är C du håller på med och i C så har varabler ett begränsat scope, en begränsad räckvidd. Denna styr dels varifrån variabeln syns, och dels styr det hur länge variabeln finns kvar.

Du kan t.ex. skapa lokala variabler inom ett block (med { och } runt).


Rekursiva funktioner ska du kanske också läsa på, att anropa en funktion är inte samma sak som "goto" i basic... Anropar du en funktion inifrån sig själv så skapas en kopia av funktionen.
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Normalt att det blir bugg om man anropar funktion i funk

Inlägg av sodjan »

Det här är väl precis samma fråga som var uppe för ett par månader sedan:
http://elektronikforumet.com/forum/view ... =7&t=71531
"Hur radera alla variabler på en linje?".

Löste det sig inte då?
Eller vad är det som har tillkommit idag?
Det var flera som försökte förklara problemen med rekursiva anrop.

> Anropar du en funktion inifrån sig själv så skapas en kopia av funktionen.

Nja... Så skulle jag inte utrycka det. Det skapas en kapia av (vissa) variabler.
Funktionen i sig (d.v.s koden) behöver inte kopieras.
Nerre
Inlägg: 27229
Blev medlem: 19 maj 2008, 07:51:04
Ort: Upplands väsby

Re: Normalt att det blir bugg om man anropar funktion i funk

Inlägg av Nerre »

Jag försökte förklara på Al´s nivå :)

Det som händer är ju att funktionens lokala variabler pushas på stacken tillsammans med returadressen.

Och en jättevanlig fälla är ju att man anropar en rekursiv funktion med en pekare till data man ska bearbeta... (I vissa lägen är det ju önskvärt, om man t.ex. gör nån form av rekursiv bearbetning av en sträng och ska stega sig igenom den.)
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Normalt att det blir bugg om man anropar funktion i funk

Inlägg av sodjan »

Jo visst, men i detta fall ska det med 100% säkerhet inte vara rekursivt alls... :-)
Men som sagt, det utreddes ju i förra tråden. Vi får se vad som har tillkommit nu.
Användarvisningsbild
Al_Bundy
Inlägg: 2889
Blev medlem: 11 september 2012, 23:59:50
Ort: The U.S - Chicago
Kontakt:

Re: Normalt att det blir bugg om man anropar funktion i funk

Inlägg av Al_Bundy »

Nerre skrev:Jag förstår inte vara du pratar om, men du behöver nog läsa på om globala och lokala variabler och framförallt vilket scope som gäller för en variabel.

Jag antar att det är C du håller på med och i C så har varabler ett begränsat scope, en begränsad räckvidd. Denna styr dels varifrån variabeln syns, och dels styr det hur länge variabeln finns kvar.

Du kan t.ex. skapa lokala variabler inom ett block (med { och } runt).


Rekursiva funktioner ska du kanske också läsa på, att anropa en funktion är inte samma sak som "goto" i basic... Anropar du en funktion inifrån sig själv så skapas en kopia av funktionen.
Det är C jag håller på med.

Nja, jag ska posta en del av min kod.

Kod: Markera allt

int set_values(int choise, int i)
{
  int part[] = {1,2,3,4,5};
  int temponary_value;
  int values_storage[10];
  String labels[5][5] = { {"*****TIME*****", "Dv0 time:", "Range 30-99:", String(values_storage[0]), String(values_storage[1]) },
                          {"*****TEMP*****", "Dv0 temp:", "Range 50-99:", String(values_storage[2]), String(values_storage[3]) },
                          {"*****TIME*****", "Dv1 time:", "Range 30-99:", String(values_storage[4]), String(values_storage[5]) },
                          {"*****TEMP*****", "Dv1 temp:", "Range 50-99:", String(values_storage[6]), String(values_storage[7]) },
                          {"***END TEMP***", "End temp:", "Range 50-99:", String(values_storage[8]), String(values_storage[9]) }};
  if (choise == 300) // 300 is complete brewing
  {
    while(i < 5)
    {
      display.clearDisplay(); // remove everything on the display
      
      // Display Menu, regulator and grades
      display.print(labels[i][0]);
      display.println(labels[i][1]);
      display.println(labels[i][2]);
      display.println(i);
      display.display();
      
      // Add first number
      values_storage[i + i] = tangent_key(choise, i);
      display.print(values_storage[i + i]);
      display.display();
      delay(500); // just to slow down
      
      // Add second number
      values_storage[i + i + 1] = tangent_key(choise, i);
      display.print(values_storage[i + i + 1]);
      display.display();
      delay(2000);
Om jag skulle mitt i koden anropa funktionen IGEN för att läsa om frågan och börja på nytt så skriver jag en extra rad som heter set_values(choise, i) där choise är 300 och i är antingen 0 eller 1,2,3,4.

Första gången jag gör det så fungerar det. Men ska jag anropa funktionen igen så buggar programmet ihop.
Löste det sig inte då?
Eller vad är det som har tillkommit idag?
Det var flera som försökte förklara problemen med rekursiva anrop.
Jag visste redan från början vid programmeringen att anropa funktion i en funktion så "snurrar" man till det i koden. Men det löste sig för mig. Just nu har jag bytt till Windows 8, ny Arduino IDE och nya drivrutiner och då har jag fått lov att skriva om HELA programmet. Därför är jag på samma problem igen.
Användarvisningsbild
Al_Bundy
Inlägg: 2889
Blev medlem: 11 september 2012, 23:59:50
Ort: The U.S - Chicago
Kontakt:

Re: Normalt att det blir bugg om man anropar funktion i funk

Inlägg av Al_Bundy »

Nerre skrev:Jag försökte förklara på Al´s nivå:)

Det som händer är ju att funktionens lokala variabler pushas på stacken tillsammans med returadressen.

Och en jättevanlig fälla är ju att man anropar en rekursiv funktion med en pekare till data man ska bearbeta... (I vissa lägen är det ju önskvärt, om man t.ex. gör nån form av rekursiv bearbetning av en sträng och ska stega sig igenom den.)
Så har du något förslag på hur man kan göra för att göra så programmet "glömmer bort" sin gamla väg?
För jag antar att om man anropar funktion i en funktion rätt många gånger så orkar inte processorn bära med sig alla gamla minnen och då kraschar det?
Nerre
Inlägg: 27229
Blev medlem: 19 maj 2008, 07:51:04
Ort: Upplands väsby

Re: Normalt att det blir bugg om man anropar funktion i funk

Inlägg av Nerre »

Mitt bästa förslag är att du läser några böcker om strukturerad programmering.

JSP (Jackson Structured Programming) har "manuella" strukturer för hur man gör "rollback", man måste hålla reda på hur långt man kommit för att veta hur långt man ska backa. För varje steg du tar framåt i din kod så ska du i slutet av koden lägga in en kod som "ångrar" det du har gjort. När du sen ska avbryta så hoppar du (enklast med select-case i C) till "rätt" ställe i din avbrottskod och går igenom de "backsteg" som behövs.
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Normalt att det blir bugg om man anropar funktion i funk

Inlägg av sodjan »

> Så har du något förslag på hur man kan göra för att göra så programmet "glömmer bort" sin gamla väg?

Alla funktioner måste komma till "slut" (return) innan de kan anropas igen.
Finns ingen annan metod.

Om du tror att set_values() måste anropas inifrån set_values() så har
du sannolikt tänkt fel.
Användarvisningsbild
Al_Bundy
Inlägg: 2889
Blev medlem: 11 september 2012, 23:59:50
Ort: The U.S - Chicago
Kontakt:

Re: Normalt att det blir bugg om man anropar funktion i funk

Inlägg av Al_Bundy »

Nerre skrev:Mitt bästa förslag är att du läser några böcker om strukturerad programmering.

JSP (Jackson Structured Programming) har "manuella" strukturer för hur man gör "rollback", man måste hålla reda på hur långt man kommit för att veta hur långt man ska backa. För varje steg du tar framåt i din kod så ska du i slutet av koden lägga in en kod som "ångrar" det du har gjort. När du sen ska avbryta så hoppar du (enklast med select-case i C) till "rätt" ställe i din avbrottskod och går igenom de "backsteg" som behövs.
Ja, men så tänker jag också. Jag är oftast van att programmera just för PC och då kan man hålla på och anropa funktioner nästan hur många gånger som helst.
Alla funktioner måste komma till "slut" (return) innan de kan anropas igen.
Finns ingen annan metod.


Om du tror att set_values() måste anropas inifrån set_values() så har
du sannolikt tänkt fel.
Hur menar du? Menar du att en funktion ska köras helt rent av och sedan anropa en annan funktion?
funk1()
{
// lite kod här
// sista raden
funk2();
}

funk2()
{

}
eller?
johano
Inlägg: 1943
Blev medlem: 22 januari 2008, 10:07:45
Ort: Stockholm

Re: Normalt att det blir bugg om man anropar funktion i funk

Inlägg av johano »

Problem som kan uppstå (speciellt på små uC) är att stacken tar slut om man börjar "kedja" ihop funktioner/anropa dem rekursivt..

Att det funkar på PC beror bara på att stacken där är såpass mycket större att du ännu inte
stött på din bugg...men, fortsätter du köra så kommer den bita dig där också, förr eller senare.

Om du nu har behov av att köra en funktion "på nytt" så finns det ett sätt att returnera ett värde
som den anropande (yttre) koden kan kolla på.

t.ex. såhär:

Kod: Markera allt


#define SUCCESS = 0;
#define RUN_ME_AGAIN = 1;

main()
{
    int retcode;
    do
    {
       retcode = funk1();

    } while( retcode == RUN_ME_AGAIN );
    ...
}

funk1()
{
  ... 
  GÖR EN MASSA SAKER
  ...

  if( User_Pressed_Back_Button )
     return RUN_ME_AGAIN;

  ... 

  return SUCCESS;
}

/johan
Användarvisningsbild
TomasL
EF Sponsor
Inlägg: 46974
Blev medlem: 23 september 2006, 23:54:55
Ort: Borås
Kontakt:

Re: Normalt att det blir bugg om man anropar funktion i funk

Inlägg av TomasL »

Dit problem är följande rader kod:
int values_storage[10];
String labels[5][5] =
Vid varje anrop av din funktion skapar du en ny "String labels" iom att det är en lokal variabel, efter ett par varv har du käkat upp allt minne (215 bytes per varv).
Du måste nog deklarera dessa två strängar som globala eller möjligtvis statiska variabler.
ElectricNooB
Inlägg: 600
Blev medlem: 26 juli 2011, 20:58:06

Re: Normalt att det blir bugg om man anropar funktion i funk

Inlägg av ElectricNooB »

Som johano säger så kommer ju fylla stacken efter ett tag, du får helt enkelt hitta ett annat sätt att lösa det på. Det är det som är kul med µC'n, hårdvaran beter sig mycket mer som en dator! :)
Användarvisningsbild
Al_Bundy
Inlägg: 2889
Blev medlem: 11 september 2012, 23:59:50
Ort: The U.S - Chicago
Kontakt:

Re: Normalt att det blir bugg om man anropar funktion i funk

Inlägg av Al_Bundy »

Jag förstog din kod och tyckte det var rätt bra, men visst är det typ nu man ska använda pekare?

Jag gillar denna typ av utmaning :)
Användarvisningsbild
Al_Bundy
Inlägg: 2889
Blev medlem: 11 september 2012, 23:59:50
Ort: The U.S - Chicago
Kontakt:

Re: Normalt att det blir bugg om man anropar funktion i funk

Inlägg av Al_Bundy »

TomasL skrev:Dit problem är följande rader kod:
int values_storage[10];
String labels[5][5] =
Vid varje anrop av din funktion skapar du en ny "String labels" iom att det är en lokal variabel, efter ett par varv har du käkat upp allt minne (215 bytes per varv).
Du måste nog deklarera dessa två strängar som globala eller möjligtvis statiska variabler.
Jo, jag kände detta att detta käkar upp mycket minne när man läser om funktionen igen. :)
Skriv svar