Apa yang terjadi jika ada kesalahan runtime?

17

Apa yang terjadi jika ada kesalahan runtime dalam suatu program? Apakah eksekusi program hanya akan berhenti? Apakah ada cara agar Arduino memberi tahu saya apa kesalahannya?

The Guy with The Hat
sumber

Jawaban:

21

Pertama, mari kita lihat beberapa contoh tentang apa yang salah.

Variabel lokal tidak diinisialisasi

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

Seperti yang ditunjukkan oleh Edgar Bonet dalam komentar, variabel lokal seperti statuspada kode di atas tidak secara implisit diinisialisasi oleh kompiler C ++. Jadi, hasil dari kode di atas tidak pasti. Untuk menghindari itu, pastikan Anda selalu memberikan nilai ke variabel lokal Anda.

Hal-hal yang sedikit berbeda dengan variabel global dan statis:

Variabel global dan statis dijamin akan diinisialisasi ke 0 oleh standar C.

Sumber: AVR Libc Reference Manual - Pertanyaan yang Sering Diajukan - Tidakkah saya harus menginisialisasi semua variabel saya?

Itu berarti Anda tidak perlu khawatir tentang inisialisasi mereka ke 0 dalam kode Anda. Bahkan, Anda harus benar-benar menghindarinya, karena inisialisasi dapat menghabiskan memori. Hanya inisialisasi mereka ke nilai selain 0.

Memori meluap

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

Masalah pertama di sini adalah bahwa Anda tidak tahu apa yang akan ditugaskan ke v, tetapi lebih buruk adalah bahwa Anda tidak tahu apa yang Anda kacau dengan tugas ke posisi -100 dari array.

Lompat ke instruksi ilegal

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
}

Panggilan pertama ke funcPtr()sebenarnya adalah panggilan ke doSomething(). Panggilan seperti panggilan kedua dapat menyebabkan perilaku yang tidak terdefinisi.

Hal buruk lain yang mungkin terjadi

Nah, Anda bisa kehabisan RAM, misalnya. Apa lagi. Bagaimanapun, saya pikir program Anda akan tetap berjalan, mungkin bukan seperti yang Anda inginkan.

Jenis Perlindungan

Dalam sistem komputer, masalah seperti ini biasanya ditangani pada berbagai tingkatan:

  1. Oleh kompiler
  2. Oleh runtime bahasa pemrograman (seperti di Jawa misalnya).
  3. Oleh sistem operasi atau prosesor (jika memori Anda mengakses posisi di luar batas ruang alamat yang disediakan untuk program Anda, OS atau prosesor mungkin memiliki mekanisme keamanan untuk mencegahnya)

Arduino hanya memiliki perlindungan terbatas pada kompiler, dan mungkin tidak ada yang lain. Berita baiknya adalah mereka tidak multi-tugas, jadi satu-satunya program yang terpengaruh adalah milik Anda. Bagaimanapun, salah satu bug itu akan menyebabkan perilaku yang tidak menentu.

Jawaban

Asumsinya adalah semua masalah yang saya nyatakan di atas adalah masalah runtime.

Apa yang terjadi jika ada kesalahan runtime dalam suatu program?

Program akan berlanjut dan apa yang terjadi akan tergantung pada efek samping dari kesalahan runtime. Panggilan ke pointer fungsi nol mungkin akan membuat program melompat ke lokasi yang tidak diketahui.

Apakah eksekusi program hanya akan berhenti?

Tidak, itu akan terus berjalan seolah-olah tidak ada yang luar biasa terjadi, mungkin melakukan apa yang tidak Anda inginkan. Ini dapat mengatur ulang atau bertindak tidak menentu. Mungkin mengubah beberapa input menjadi output dan membakar satu atau dua sensor (tapi itu sangat tidak mungkin ).

Apakah ada cara saya mendapatkan Arduino untuk memberi tahu saya apa kesalahannya?

Saya kira tidak. Seperti yang saya katakan sebelumnya, mekanisme perlindungan tidak ada. Tidak ada dukungan runtime dari bahasa, tidak ada OS, tidak ada perangkat keras yang memeriksa akses memori di luar batas (bootloader tidak masuk hitungan juga). Anda hanya harus berhati-hati dengan program Anda dan mungkin mengatur jaring pengaman Anda sendiri.

Alasan kurangnya perlindungan mungkin karena pengontrol Arduino terlalu murah, memiliki memori terlalu sedikit, dan tidak boleh menjalankan sesuatu yang terlalu penting (ya, sepertinya ada penafian oleh AVR di suatu tempat bagi Anda untuk tidak menggunakan MCU yang biasanya digunakan oleh Arduino dalam sistem pendukung kehidupan).

Ricardo
sumber
1
Bagus! Jawaban terbaik yang saya lihat di Arduino.SE sejauh ini!
The Guy with The Hat
1
Terima kasih!! Saya pikir kita harus berusaha untuk memberikan jawaban sebanyak mungkin. Tapi itu sedikit membuatku khawatir karena kita tidak memiliki begitu banyak AHLI NYATA yang bisa melihat jawaban seperti milikku dan menemukan kesalahan yang mencolok. Sebenarnya, itulah alasan saya mengirim jawaban meskipun saya tidak tahu banyak tentang AVR MCU. Itu untuk melihat apakah kita mendapatkan seseorang untuk memperbaikinya. Kami yakin tidak ingin pents cerdas seperti saya mengatakan hal-hal yang tidak benar dan lolos begitu saja. Tapi itu mungkin diskusi untuk situs Meta.
Ricardo
5
@ Ricardo - Satu komentar yang akan saya buat adalah bahwa variabel yang diinisialisasi secara non-eksplisit belum tentu diinisialisasi. Variabel yang didefinisikan di luar fungsi umumnya memiliki apa yang disebut "durasi penyimpanan otomatis", yang kemudian mendapatkan inisialisasi default ke nol. Lihat en.cppreference.com/w/cpp/language/default_initialization untuk informasi lebih lanjut. Perilaku inisialisasi cukup kompleks sehingga mungkin berbahaya untuk diandalkan, tetapi membuat pernyataan selimut mungkin bukan ide yang bagus.
Connor Wolf
1
Lebih lanjut, SRAM diinisialisasi ke 0 pada saat reset atau startup, sehingga Anda dapat membuat beberapa tebakan informasi tentang variabel yang tidak diinisialisasi, jika Anda ingin hidup dengan berbahaya. Anda seharusnya tidak mengandalkan perilaku ini, tetapi ini menarik.
Connor Wolf
1
Ada contoh menarik tentang apa yang terjadi ketika Anda kehabisan SRAM di sini: electronics.stackexchange.com/questions/42049/… . Pada dasarnya, tumpukan clobbers bagian dari heap, atau sebaliknya. Ini dapat melakukan hal-hal menarik seperti merusak beberapa bagian dari tumpukan-bingkai (fungsi pemutusan pengembalian, dll), atau menulis data yang tidak valid ke variabel.
Connor Wolf
9

Tidak ada pengecualian runtime. Hanya ada perilaku yang tidak terdefinisi.

Sungguh, tidak ada pengecualian sama sekali . Jika Anda mencoba melakukan operasi yang tidak valid, hasilnya tidak akan diketahui.

Tidak ada pemeriksaan runtime sama sekali, kecuali apa yang Anda implementasikan. Program Anda berjalan pada perangkat keras logam. Ini setara dengan Desktop yang berjalan di ring-0 sepanjang waktu, karena ATmega tidak memiliki dering .

Connor Wolf
sumber
6

Ada satu mekanisme yang bisa mendapatkan MCU dari keadaan tidak menentu dan itu adalah pengawas waktu . Jika Anda menerapkan beberapa kode yang berulang kali berjalan dalam satu lingkaran, yang tidak akan berjalan lebih lama dari waktu tertentu, Anda dapat mengatur waktu ini sebagai periode pengawas dan mengaktifkan timer.

Kemudian, Anda harus berulang kali mereset timer dalam loop. Jika kode Anda membeku di beberapa loop kondisi yang tidak akan pernah berakhir, maka pengawas akan menghitung ke nol dan akhirnya mengatur ulang MCU.

Dengan cara ini Anda kehilangan data, tetapi jika Anda menjalankan AVR WDT dalam mode interupsi, Anda dapat menyimpan beberapa data sebelum mengatur ulang MCU.

Jadi pengawas waktu dapat menjaga kode Anda dari loop tak berujung sesekali yang tidak diinginkan.

Dokumentasi: AVR132: Menggunakan Timer Watchdog Enhanced

nio
sumber
5

Anda memerlukan debugger perangkat keras untuk hal seperti ini. Tetapi biasanya Anda akan melihat program tidak berperilaku seperti yang Anda harapkan dan harus melihat bagian kode untuk mengidentifikasi masalah.

Cara umum / cepat / mudah untuk melakukan ini adalah menambahkan pernyataan cetak untuk mencetak nilai-nilai variabel atau apa saja sehingga Anda tahu program sampai pada titik itu dalam kode tanpa masalah. Ini akan membantu Anda mengisolasi masalah lebih lanjut.

Saya percaya VisualMicro memiliki beberapa fungsi debugging bawaan .

sachleen
sumber
3

Saya akan berasumsi AVR CPU tidak memiliki alat deteksi kesalahan atau pemulihan. Mungkin saja berhenti, atau terus mengabaikan kesalahan dan konsekuensinya. Seperti kata sachleen, Anda harus menambahkan beberapa pernyataan debug di program Anda yang mencetak data di tengah operasi, untuk menguji apakah itu berfungsi. Jika Anda menggunakan emulaor dan mengatur breakpoint, Anda dapat dengan mudah menemukan masalah.

Dokter
sumber
-2

Arduino akan reboot (yaitu akan meluncurkan kembali setup()dan loop()).

pengguna28739
sumber
1
Belum tentu. Kesalahan run-time mungkin membuat program menjadi berulang tanpa me-reboot.
Nick Gammon