จะเกิดอะไรขึ้นหากมีข้อผิดพลาดรันไทม์?


17

จะเกิดอะไรขึ้นหากมีข้อผิดพลาดรันไทม์ในโปรแกรม การทำงานของโปรแกรมจะหยุดลงหรือไม่ มีวิธีที่ฉันได้รับ Arduino บอกฉันว่าข้อผิดพลาดคืออะไร?

คำตอบ:


21

ก่อนอื่นเรามาดูตัวอย่างของสิ่งที่ผิดพลาด

ตัวแปรท้องถิ่นที่ไม่ได้กำหนดค่าเริ่มต้น

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

ดังที่Edgar Bonetชี้ให้เห็นในความคิดเห็นตัวแปรท้องถิ่นเช่นเดียวกับstatusในโค้ดข้างต้นไม่ได้เริ่มต้นโดยคอมไพเลอร์ C ++ ดังนั้นผลลัพธ์ของโค้ดข้างต้นจึงไม่แน่นอน เพื่อหลีกเลี่ยงปัญหานี้ตรวจสอบให้แน่ใจว่าคุณกำหนดค่าให้กับตัวแปรท้องถิ่นของคุณเสมอ

สิ่งที่แตกต่างกันเล็กน้อยกับตัวแปรทั่วโลกและคงที่:

ตัวแปรโกลบอลและสแตติกรับประกันว่าจะเริ่มต้นได้ถึง 0 โดยมาตรฐาน C

แหล่งที่มา: คู่มืออ้างอิง AVR Libc - คำถามที่พบบ่อย - ฉันไม่ควรเริ่มต้นตัวแปรทั้งหมดของฉันหรือไม่

นั่นหมายความว่าคุณไม่ต้องกังวลเกี่ยวกับการเริ่มต้นเป็น 0 ในรหัสของคุณ ในความเป็นจริงคุณควรหลีกเลี่ยงเพราะการเริ่มต้นอาจทำให้หน่วยความจำเสีย กำหนดค่าเริ่มต้นเป็นค่าอื่นที่ไม่ใช่ 0 เท่านั้น

หน่วยความจำล้น

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

ปัญหาแรกที่นี่เป็นที่ที่คุณไม่ทราบว่าสิ่งที่จะได้รับมอบหมายให้โวลต์ แต่เลวร้ายก็คือว่าคุณไม่ได้รู้ว่าสิ่งที่คุณ messed up ที่มีการกำหนดให้อยู่ในตำแหน่ง -100 arrayของ

ข้ามไปยังคำสั่งที่ผิดกฎหมาย

void doSomething( void ) { 
    for (int i = 0; i < 1000; i++); 
}

void setup () 
{
    void (*funcPtr)( void );

    funcPtr = &doSomething;
    funcPtr(); // calls doSomething();

    funcPtr = NULL;
    funcPtr(); // undefined behavior
}

สายแรกที่จะจริงจะเรียกไปยังfuncPtr() doSomething()การโทรอย่างที่สองอาจนำไปสู่พฤติกรรมที่ไม่ได้กำหนด

สิ่งเลวร้ายอื่น ๆ ที่อาจเกิดขึ้น

ตัวอย่างเช่นคุณสามารถใช้ RAM หมดได้ อะไรอีกนะ ไม่ว่าในกรณีใดฉันคิดว่าโปรแกรมของคุณจะยังคงทำงานต่อไปอาจไม่ใช่วิธีที่คุณตั้งใจจะทำ

ชนิดของการป้องกัน

ในระบบคอมพิวเตอร์ปัญหาเช่นนี้มักเกิดขึ้นในระดับต่าง ๆ :

  1. โดยคอมไพเลอร์
  2. โดยการเขียนโปรแกรมภาษารันไทม์ (เช่นใน Java เช่น)
  3. โดยระบบปฏิบัติการหรือโปรเซสเซอร์ (หากหน่วยความจำของคุณเข้าถึงตำแหน่งนอกขอบเขตของพื้นที่ที่อยู่ที่สงวนไว้กับโปรแกรมของคุณระบบปฏิบัติการหรือโปรเซสเซอร์อาจมีกลไกความปลอดภัยเพื่อป้องกันไม่ให้เกิด)

Arduinos มีการป้องกันคอมไพเลอร์อย่าง จำกัด และอาจไม่มีอะไรอื่น ข่าวดีก็คือว่าพวกเขาไม่ได้ทำงานหลายงานดังนั้นโปรแกรมเดียวที่ได้รับผลกระทบเป็นของคุณ ไม่ว่าในกรณีใดข้อบกพร่องใด ๆ เหล่านั้นจะนำไปสู่พฤติกรรมที่ไม่แน่นอน

คำตอบ

สมมติฐานเป็นปัญหาทั้งหมดที่ฉันระบุไว้ข้างต้นเป็นปัญหารันไทม์

จะเกิดอะไรขึ้นหากมีข้อผิดพลาดรันไทม์ในโปรแกรม

โปรแกรมจะดำเนินการต่อและสิ่งที่เกิดขึ้นจะขึ้นอยู่กับผลข้างเคียงของข้อผิดพลาดรันไทม์ การเรียกไปที่ตัวชี้ฟังก์ชัน null อาจทำให้โปรแกรมข้ามไปยังตำแหน่งที่ไม่รู้จัก

การทำงานของโปรแกรมจะหยุดลงหรือไม่

ไม่มันจะดำเนินต่อไปราวกับว่าไม่มีอะไรพิเศษเกิดขึ้นอาจทำในสิ่งที่คุณไม่ได้ตั้งใจจะทำ อาจรีเซ็ตหรือทำงานผิดปกติ มันอาจจะเปลี่ยนปัจจัยการผลิตบางอย่างเป็นผลและการเผาไหม้เซ็นเซอร์หรือสอง ( แต่ที่ไม่น่าจะสูง )

มีวิธีที่ฉันได้รับ Arduino บอกฉันว่าข้อผิดพลาดคืออะไร?

ฉันไม่คิดอย่างนั้น อย่างที่ฉันพูดไปก่อนหน้านี้กลไกการป้องกันไม่ได้อยู่ที่นั่น ไม่มีการสนับสนุนรันไทม์จากภาษาไม่มีระบบปฏิบัติการไม่มีฮาร์ดแวร์ตรวจสอบการเข้าถึงหน่วยความจำนอกขอบเขต (bootloader ไม่นับรวม) คุณเพียงแค่ต้องระมัดระวังโปรแกรมของคุณและอาจตั้งอวนความปลอดภัยของคุณเอง

เหตุผลที่ขาดการป้องกันอาจเป็นเพราะตัวควบคุม Arduino ราคาถูกเกินไปมีหน่วยความจำน้อยเกินไปและไม่ควรรันอะไรที่สำคัญเกินไป (ใช่ดูเหมือนว่าจะมีข้อจำกัดความรับผิดชอบจาก AVR สำหรับคุณที่จะไม่ใช้ MCU ตามปกติ Arduino ในระบบช่วยชีวิต)


1
ที่ดี! คำตอบที่ดีที่สุดที่ฉันเคยเห็นใน Arduino.SE จนถึงตอนนี้!
The Guy with The Hat

1
ขอบคุณ !! ฉันคิดว่าเราควรพยายามให้คำตอบที่ดีที่สุดเท่าที่จะทำได้ แต่มันทำให้ฉันกังวลเล็กน้อยเกี่ยวกับความจริงที่ว่าเราไม่มีผู้เชี่ยวชาญด้าน EE จำนวนมากที่สามารถมองหาคำตอบเหมือนของฉันและพบข้อผิดพลาดที่จ้องมอง ที่จริงแล้วนั่นคือเหตุผลที่ฉันโพสต์คำตอบแม้ว่าฉันจะไม่รู้เกี่ยวกับ AVR MCU เพื่อดูว่าเราให้ใครซักคนมาแก้ไขไหม เราแน่ใจว่าไม่ต้องการเพ็นท์อัจฉริยะอย่างที่ฉันพูดในสิ่งที่ไม่ถูกต้องและหลบไปกับมัน แต่นั่นอาจเป็นการอภิปรายสำหรับเว็บไซต์ Meta
Ricardo

5
@Ricardo - หนึ่งความคิดเห็นที่ฉันจะทำก็คือตัวแปรที่เริ่มต้นไม่ชัดเจนไม่จำเป็นต้องเตรียม ตัวแปรที่กำหนดไว้นอกฟังก์ชั่นโดยทั่วไปมีสิ่งที่เรียกว่า "ระยะเวลาการจัดเก็บอัตโนมัติ" ซึ่งจะได้รับการเริ่มต้นให้เป็นศูนย์ ดูen.cppreference.com/w/cpp/language/default_initializationสำหรับข้อมูลเพิ่มเติม พฤติกรรมการเริ่มต้นนั้นซับซ้อนพอที่อาจเป็นอันตรายได้ แต่การสร้างข้อความครอบคลุมอาจไม่ใช่ความคิดที่ดี
Connor Wolf

1
นอกจากนี้ SRAM จะเริ่มต้นเป็น 0 เมื่อรีเซ็ตหรือเริ่มต้นดังนั้นคุณสามารถคาดเดาบางอย่างเกี่ยวกับตัวแปรที่ไม่กำหนดค่าเริ่มต้นหากคุณต้องการมีชีวิตที่เป็นอันตราย คุณไม่ควรพึ่งพาพฤติกรรมนี้ แต่มันน่าสนใจ
Connor Wolf

1
มีตัวอย่างที่น่าสนใจของสิ่งที่เกิดขึ้นเมื่อคุณทำงานออกจาก SRAM นี่คือelectronics.stackexchange.com/questions/42049/... โดยพื้นฐานแล้วสแต็คจะแยกส่วนของฮีปหรือในทางกลับกัน สิ่งนี้สามารถทำสิ่งที่น่าสนใจเช่นเสียหายบางส่วนของกรอบสแต็ก (การทำลายฟังก์ชันส่งคืน ฯลฯ ) หรือการเขียนข้อมูลที่ไม่ถูกต้องไปยังตัวแปร
Connor Wolf

9

ไม่มีข้อยกเว้นรันไทม์ มีพฤติกรรมที่ไม่ได้กำหนดเท่านั้น

จริงๆมีข้อยกเว้นไม่ได้ทั้งหมด หากคุณพยายามทำการดำเนินการที่ไม่ถูกต้องผลลัพธ์จะไม่เป็นที่รู้จัก

ไม่มีการตรวจสอบรันไทม์เลยยกเว้นสิ่งที่คุณใช้ โปรแกรมของคุณกำลังทำงานบนฮาร์ดแวร์โลหะเปลือย มันเป็นเทียบเท่าสก์ท็อปของการทำงานในแหวน 0ตลอดเวลาเพราะ ATMEGA ไม่ได้มีแหวน


6

มีกลไกหนึ่งที่จะได้รับจากรัฐ MCU ที่ผิดปกติและมันเป็นเวลาจ้องจับผิด หากคุณกำลังใช้รหัสบางอย่างที่จะทำงานซ้ำ ๆ ในลูปซึ่งจะไม่ทำงานนานกว่าเวลาที่กำหนดคุณสามารถตั้งค่าเวลานี้เป็นช่วงจ้องจับผิดและเปิดใช้งานตัวจับเวลา

จากนั้นคุณต้องรีเซ็ตตัวจับเวลาซ้ำ ๆ ในลูป หากรหัสของคุณค้างที่เงื่อนไขบางอย่างที่จะไม่สิ้นสุดแล้วจ้องจับผิดจะนับเป็นศูนย์และในที่สุดรีเซ็ต MCU

วิธีนี้คุณกำลังสูญเสียข้อมูล แต่ถ้าคุณเรียกใช้ AVR WDT ในโหมดขัดจังหวะคุณสามารถจัดเก็บข้อมูลบางอย่างก่อนที่จะรีเซ็ต MCU

ดังนั้นตัวจับเวลาจ้องจับผิดสามารถป้องกันโค้ดของคุณจากการวนซ้ำไม่รู้จบเป็นครั้งคราว

เอกสารประกอบ: AVR132: การใช้ตัวจับเวลา Watchdog ขั้นสูง


5

คุณต้องการตัวแก้ไขข้อบกพร่องฮาร์ดแวร์สำหรับสิ่งนี้ แต่โดยปกติคุณจะเห็นโปรแกรมไม่ทำงานตามที่คุณคาดหวังและจะต้องดูที่ส่วนของรหัสเพื่อระบุปัญหา

วิธีการทั่วไป / รวดเร็ว / ง่ายในการทำเช่นนี้คือการเพิ่มคำสั่งการพิมพ์เพื่อพิมพ์ค่าของตัวแปรหรืออะไรก็ได้เพื่อให้คุณรู้ว่าโปรแกรมไปถึงจุดนั้นในโค้ดโดยไม่มีปัญหา สิ่งนี้จะช่วยคุณแยกปัญหาเพิ่มเติม

ฉันเชื่อว่าVisualMicroมีฟังก์ชันการแก้ไขข้อบกพร่องบางอย่างในตัว


3

ฉันคิดว่า AVR CPU ไม่มีเครื่องมือตรวจจับข้อผิดพลาดหรือการกู้คืน มันอาจหยุดหรือไม่สนใจข้อผิดพลาดและผลที่ตามมา เช่นเดียวกับ sachleen ที่กล่าวว่าคุณควรเพิ่มคำสั่ง debug บางอย่างในโปรแกรมของคุณที่พิมพ์ข้อมูลในระหว่างการดำเนินการเพื่อทดสอบว่ามันทำงานได้หรือไม่ หากคุณใช้ emulaor และตั้งจุดพักคุณสามารถค้นหาปัญหาได้อย่างง่ายดาย


-2

Arduino จะเริ่มต้นใหม่ (เช่นจะเปิดใหม่setup()และloop())


1
ไม่จำเป็น. ข้อผิดพลาดรันไทม์อาจทำให้โปรแกรมเข้าสู่ลูปโดยไม่ต้องบูตเครื่องใหม่
Nick Gammon
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.