Küsimus:
Mis juhtub, kui esineb käitamisviga?
The Guy with The Hat
2014-02-14 07:33:03 UTC
view on stackexchange narkive permalink

Mis juhtub, kui programmis on käitusviga? Kas programmi täitmine lihtsalt peatub? Kas saan kuidagi Arduino käest öelda, mis viga on?

Kuus vastused:
#1
+21
Ricardo
2014-02-15 03:24:20 UTC
view on stackexchange narkive permalink

Kõigepealt vaatame mõnda näidet, mis võib valesti minna.

Initsialiseerimata lokaalsed muutujad

  void setup () {int status; pinMode (13, OUTPUT); digitalWrite (13, status);} 

Nagu märkis Edgar Bonet, on koodis kohalikud muutujad nagu status ülaltoodud ei ole C ++ kompilaatori poolt vaikimisi initsialiseeritud. Niisiis, ülaltoodud koodi tulemus on määramatu. Selle vältimiseks määrake oma kohalikele muutujatele alati väärtused.

Asjad on globaalsete ja staatiliste muutujatega natuke erinevad:

Globaalsed ja staatilised muutujad on tagatud lähtestada C-standardi järgi väärtuseni 0.

Allikas: AVR Libc Reference Manual - korduma kippuvad küsimused - kas ma ei peaks kõiki oma muutujaid lähtestama?

See tähendab, et te ei peaks muretsema nende koodis nullimise eest. Tegelikult peaksite seda tõesti vältima, kuna lähtestamine võib mälu raisata. Initsialiseerige need ainult muudele väärtustele kui 0.

Mälu ületäitumine

  int massiiv [10]; int v = array [100]; array [-100] = 10; 

Esimene probleem on siin see, et te ei tea, mis v-le määratakse, kuid halvem on see, et te ei tea, mida ajasite -100 array.

Mine ebaseadusliku käsu juurde

  void doSomething (void) {for (int i = 0; i < 1000; i ++) ; } void setup () {void (* funcPtr) (void); funcPtr = &doSomething; funcPtr (); // kutsub doSomething (); funcPtr = NULL; funcPtr (); // määratlemata käitumine}  

Esimene kõne funcPtr () on tegelikult kutse doSomething () . Teise moodi kõned võivad viia määratlemata käitumiseni.

Muud halvad asjad, mis võivad juhtuda

Noh, näiteks võib RAM otsa saada. Mida veel. Igal juhul arvan, et teie programm töötab edasi, tõenäoliselt mitte nii, nagu kavatsesite.

Kaitseliigid

Arvutisüsteemides lahendatakse selliseid probleeme tavaliselt erinevatel tasanditel:

  1. kompilaatori poolt
  2. programmeerimiskeele käitusaja järgi (nagu näiteks Java-s) .
  3. Operatsioonisüsteemi või protsessori poolt (kui teie mälu pääseb kohale, mis asub väljaspool teie programmile reserveeritud aadressiruumi piire, võivad operatsioonisüsteemil või protsessoril olla selle vältimiseks turvamehhanismid)

Arduinos on kompilaatori kaitse piiratud ja tõenäoliselt mitte midagi muud. Hea uudis on see, et nad ei ole mitme ülesandega, nii et ainus programm, mida see mõjutab, on teie. Igal juhul viib ükskõik milline nendest vigadest ebakorrapärase käitumiseni.

Vastused

Eeldused on kõik probleemid, mida ma eespool ütlesin, on käituse probleemid.

Mis juhtub, kui programmis on käitustõrge?

Programm jätkub ja see, mis juhtub, sõltub käituse tõrke kõrvalmõjudest. Funktsiooni pointeri null kutsumine paneb programmi tõenäoliselt tundmatusse kohta hüppama.

Kas programmi täitmine lihtsalt peatub?

Ei, see on jätkab nii, nagu poleks midagi erakordset juhtunud, tõenäoliselt tehes seda, mida te seda teha ei kavatsenud. See võib lähtestada või toimida valesti. See võib muuta mõne sisendi väljundiks ja põletada sensori või kaks (kuid see on väga ebatõenäoline ).

Kas saan Arduino kuidagi öelda, mida viga on?

Ma ei arva. Nagu ma varem ütlesin, pole kaitsemehhanisme olemas. Keele käitusaega pole olemas, operatsioonisüsteemi pole, riistvara ei kontrolli piirivälist mälu (ka alglaadur ei loe seda). Peate oma programmiga lihtsalt ettevaatlik olema ja tõenäoliselt oma turvavõrgud paika panema.

Kaitse puudumise põhjus on tõenäoliselt seetõttu, et Arduino kontrollerid on liiga odavad, liiga vähe mälu ja ei tohiks käitada midagi liiga olulist (jah, AVR näib kuskil olevat lahtiütlust, et te MCU-sid ei kasutaks tavaliselt kasutab Arduino elutoetussüsteemides).

Suurepärane! Parim vastus, mida olen Arduino.SE-s siiani näinud!
Aitäh !! Ma arvan, et peaksime püüdma anda võimalikult palju suurepäraseid vastuseid. Kuid mind teeb veidi murelikuks asjaolu, et meil pole nii palju PÄRISE EELISE EKSPERTI, kes võiksid vaadata minusuguseid vastuseid ja leida silmatorkavaid vigu. Tegelikult postitasin vastuse, kuigi ma ei tea nii palju AVR MCU-de kohta. Seda selleks, et näha, kas saame kedagi seda parandama. Me kindlasti ei taha, et minusugused nutikad pentsikud ütleksid asjad, mis pole õiged, ja pääsevad sellest. Kuid see on ilmselt Meta saidi arutelu.
Kas mõni sellest kahjustaks Arduinot?
@AnnonomusPerson - ainus tõenäoline kahjustuste tekkemehhanism oleks kood, mis muudab tihvti olekut viisil, mille tulemuseks on siinivaidlus (nt ATmega üritab seada tihvti kõrgeks, samal ajal kui väline riistvara seab selle madalaks). Samuti on võimalik, et kui välist riistvara on olemas, kontrollib ATmega, mis ei suuda teatud juhtimissisendi olekutega hakkama saada, võib * väline riistvara * põhjustada mingisuguseid tõrkeid ja häireid, kuid arduino, millel pole midagi, ühendas seda üsna kuulikindlalt. Arduinos on seeriatakistid, et vältida võimalikke vaidlusprobleeme jadaliinidel.
@Ricardo - ühe kommentaari, mille ma ütlen, on see, et selgesõnaliselt initsialiseeritud muutujaid ei ole * tingimata * initsialiseerimata. Väljaspool funktsioone määratletud muutujate nimetus on "automaatne salvestusaja kestus", mis initsialiseeritakse vaikimisi nulli. Lisateavet leiate aadressilt http://et.cppreference.com/w/cpp/language/default_initialization. Initsialiseerimiskäitumine on piisavalt keeruline, et sellele tugineda on tõenäoliselt ohtlik, kuid üldiste avalduste tegemine pole * tõenäoliselt * suurepärane idee.
Lisaks lähtestatakse SRAM lähtestamisel või käivitamisel väärtuseks 0, nii et kui soovite ohtlikult elada, võite teha * mõned * teadlikud oletused initsialiseerimata muutujate kohta. Sellele käitumisele ei tohiks loota *, kuid see on huvitav.
Siit leiate huvitava näite selle kohta, mis juhtub, kui SRAM otsa saab: http://electronics.stackexchange.com/questions/42049/arduino-serial-print-changes-behavior-of-program-undesireably/42069. Põhimõtteliselt röövib virn hunniku osa või vastupidi. See võib teha huvitavaid asju, nagu näiteks korstna raami mõne osa rikkumine (funktsiooni purustamine tagastab jne) või muutujatesse kehtetute andmete kirjutamine.
Samuti on asjakohane küsimus rekursiooni kohta: http://arduino.stackexchange.com/questions/355/how-much-can-i-recurse-how-much-can-i-recurse-how-much-caqfsdrfw kuna rekursioon on üks lihtsaid viise virna puhumiseks.
@FakeName - eks! Muudan oma vastust, et kinnitada initsialiseerimata muutujate kohta käiv väide. Mis puutub teistesse suurepärastesse ettepanekutesse, mille postitasite, siis miks te neile ei vasta ja lisan sellele minu enda viite? Tore, et näen teid siin (või võib-olla lihtsalt teie pahase kassi pilti) siinpool.
@FakeName - BTW, see pilt tuletab mulle alati 4: 57minuti jooksul meelde [Kasside inseneri juhend] (http://www.youtube.com/watch?v=mHXBL6bzAR4) suurepärast kassijodeldamise * tehnikat *.
Üks märkus: "Hea uudis on see, et ajasite segamini ainult RAM-i, mitte EEPROM-i, seega on teie programm turvaline." ATmegal töötav programm salvestatakse välkmällu, mitte EEPROM-i. EEPROM on üldjuhul ainult 1-2 KB ja mõeldud pigem väikeste koguste püsimatu andmete (mõelge: kasutaja konfiguratsiooniseaded, seerianumber jne ...), mitte tegeliku koodi salvestamiseks.
@ConnorWolf Õige! Hästi laiguline. Muutsin ja parandasin lihtsalt minu vastust.
`C ++ kompilaator teeb seda teie eest. See määrab selle nulliks. Kohalikke muutujaid ei lähtestata. Ma tõlgendan teie olekut teie näites kohalikuks, seega on see vale. "sellele käitumisele lootmist ei peeta heaks tavaks" tegelikult ** peetakse ** heaks tavaks tugineda sellele käitumisele globaalsete muutujate puhul, kuna on tagatud, et need nullitakse ja teie koodis nullivad globaalid võivad mälu raisata (kuigi praegused kompilaatorid peaksid selle vältimiseks olema piisavalt targad), vt http://www.atmel.com/webdoc/AVRLibcReferenceManual/FAQ_1faq_varinit.html
Sa kirjutasid: "_`array [-100] = 10;" [...] sa ajasid sassi ainult RAM-i [...], seega on sinu programm turvaline ._ "Võib juhtuda, et kirjutate lõpuks ka IO ruumi MCU, mis on mäluga kaardistatud AVR-de RAM-i all. See pole kindlasti _ei ohutu_. "_ [NULL-funktsiooni osutile helistamine], mis on samaväärne pehme alglaadimisega_". Mitte just. Programm taaskäivitub kohe algusest peale: see lähtestab virnaosuti, RAM-i, kõne peaosa jne. Kuid erinevalt pehmest alglaadimisest _ ei_tahvata see IO-registrite vaikesättesse.
@Connor Wolf: Kirjutasite: "_ lähtestamisel või käivitamisel lähtestatakse SRAM väärtuseks 0". See on vale. Erinevalt IO registritest ei algata riistvara SRAM-i käivitamisel. RAM-i BSS-i sektsioon (ja _ ainult see sektsioon) initsialiseeritakse C käituse ajal nulli. Jaotis DATA lähtestatakse mis tahes sisule, mida programmeerija soovis. Kogu järelejäänud RAM on initsialiseerimata.
@EdgarBonet - punkt on võetud. Kahju, et ma ei saa oma vanemaid kommentaare muuta.
@EdgarBonet - Täname, et osutasite probleemile minu vastusega. Lugesin teie esitatud linki ja proovisin parandada kohalike muutujate kohta käivaid väiteid. Kas kontrolliksite palun? Aitäh!
Teie väide programmi taaskäivitamise kohta NULL-funktsiooni osuti kutsumisel oli õige, vähemalt AVR-is. Juhtisin just tähelepanu sellele, et programmi taaskäivitamine pole päris sama mis lähtestamine. BTW, protsessis pole ebaseaduslikke juhiseid. "_Kas palun kontrolliksite seda? _" Ma ei leia teie vastusest midagi valesti.
#2
+9
Connor Wolf
2014-02-15 05:26:18 UTC
view on stackexchange narkive permalink

Käitusaja erandeid pole. On ainult määratlemata käitumist.

Tõepoolest pole erandeid üldse . Kui proovite teha valet toimingut, pole selle tulemused teada.

Käitusaega ei kontrollita üldse, välja arvatud see, mida rakendate . Teie programm töötab paljasmetallist riistvaral. See on töölaua ekvivalent, mis töötab kogu aeg ring-0, sest ATmegal pole rõngaid .

#3
+6
nio
2014-02-15 17:44:12 UTC
view on stackexchange narkive permalink

On üks mehhanism, mis võib saada MCU ebakorrapärasest olekust ja see on valvekoera taimer . Kui juurutate mõnda koodi, mis töötab korduvalt tsüklis ja mis ei tööta mingil kindlal kellaajal kauem, saate selle aja valvekoera perioodiks määrata ja taimeri lubada.

Seejärel peate taimer ringis korduvalt lähtestama. Kui teie kood hangub mõnes tingimusringis, mis ei lõpe kunagi, loendatakse valvekoer nullini ja lähtestatakse MCU lõpuks.

Nii kaotate andmeid, kuid kui käivitate AVR WDT katkestusrežiimis , saate enne MCU lähtestamist mõned andmed salvestada.

Nii saab valvur taimer kaitsta teie koodi juhuslike tahtmatute lõputute silmuste eest.

Dokumentatsioon: AVR132: täiustatud valvekoera kasutamine Taimer

#4
+5
sachleen
2014-02-14 07:47:14 UTC
view on stackexchange narkive permalink

Sellise asja jaoks vajate riistvara silurit. Kuid tavaliselt näete, et programm ei käitu nii, nagu eeldate, ja peate probleemi tuvastamiseks vaatama koodi seda jaotist.

Levinud / kiire / lihtne viis seda teha on muutujate väärtuste või mis tahes muu väärtuse väljatrükkimiseks lisage prindilaused, et teaksite, et programm jõuab koodis selle probleemita. See aitab teil probleemi veelgi isoleerida.

Usun, et VisualMicro on sisse ehitatud mõni silumisfunktsioon.

#5
+3
TheDoctor
2014-02-14 07:50:32 UTC
view on stackexchange narkive permalink

Oletan, et AVR-protsessoril pole vigade tuvastamise ega taastamise tööriistu. See võib lihtsalt peatuda või ignoreerida viga ja selle tagajärgi. Nagu ütles Sachleen, peaksite oma programmi lisama mõned silumislaused, mis prindivad andmed keset toimingut, et testida, kas see töötab. Kui kasutate emulaatorit ja määrate murdepunktid, võite probleemi hõlpsasti leida.

#6
-2
user28739
2016-12-03 04:18:45 UTC
view on stackexchange narkive permalink

Arduino taaskäivitub (st taaskäivitab setup () ja loop () ).

Mitte tingimata. Käitusaja tõrge võib viia programmi ilma taaskäivitamiseta ringi.


See küsimus ja vastus tõlgiti automaatselt inglise keelest.Algne sisu on saadaval stackexchange-is, mida täname cc by-sa 3.0-litsentsi eest, mille all seda levitatakse.
Loading...