Apa sebenarnya yang dimaksud dengan "IB" dan "UB"?

110

Saya pernah melihat istilah "IB" dan "UB" digunakan beberapa kali, terutama dalam konteks C ++. Saya sudah mencoba mencari di Google, tetapi tampaknya kombinasi dua huruf itu banyak digunakan. : P

Jadi, saya bertanya kepada Anda ... apa artinya, ketika dikatakan seolah-olah itu hal yang buruk?

cHao
sumber
5
Jika Anda memutuskan untuk membatalkan hasil edit orang lain, harap pastikan ejaan, tanda baca, dan tata bahasa Anda sudah sempurna. Memutar kembali hasil edit yang merupakan peningkatan substansial atas teks asli tidak ada gunanya.
Robert Harvey

Jawaban:

139

IB: Perilaku yang Ditentukan Penerapan. Standar menyerahkannya pada kompilator / platform tertentu untuk mendefinisikan perilaku yang tepat, tetapi mengharuskannya untuk didefinisikan.

Menggunakan perilaku yang ditentukan implementasi bisa berguna, tetapi membuat kode Anda kurang portabel.

UB: Perilaku Tidak Terdefinisi. Standar tidak menentukan bagaimana program yang menjalankan perilaku tidak terdefinisi harus berperilaku. Juga dikenal sebagai "setan hidung" karena secara teoritis bisa membuat setan terbang keluar dari hidung Anda.

Menggunakan perilaku tidak terdefinisi hampir selalu merupakan ide yang buruk. Meskipun terkadang berfungsi, perubahan apa pun pada lingkungan, kompiler, atau platform dapat merusak kode Anda secara acak.

Thomas
sumber
11
Saya masih menunggu iblis terbang keluar dari hidung seseorang karena menggunakan perilaku tidak terdefinisi dalam C ++. Saya kira itu akan terjadi ketika kompiler pertama sepenuhnya mematuhi standar C ++ baru.
OregonGhost
4
@OregonGhost: Saya rasa Anda benar. Saya telah melihat itu terjadi dengan unicorn beberapa kali, tetapi tidak pernah dengan setan.
Thomas
33
@OregonGhost - standar tidak menentukan berapa banyak tanduk yang harus dimiliki setan.
DVK
5
@ Michael Burr: Saya lebih suka "menangkap api". Ini jelas merupakan bencana, dan setidaknya memiliki kesan samar yang masuk akal (perangkat keras komputer kadang-kadang terbakar, memang karena alasan perangkat keras daripada kegagalan perangkat lunak dalam kasus sistem apa pun yang Anda gunakan untuk membaca utas ini).
Steve Jessop
1
Lucu sekali bagaimana tidak seorang pun yang menjawab pertanyaan ini memiliki reputasi kurang dari 30k.
19

Perilaku yang ditentukan implementasi dan perilaku yang tidak ditentukan

Standar C ++ sangat spesifik tentang efek berbagai konstruksi, dan khususnya Anda harus selalu waspada terhadap kategori masalah berikut :

  • Perilaku tidak terdefinisi berarti sama sekali tidak ada jaminan yang diberikan. Kode bisa bekerja, atau bisa juga membakar hard drive Anda atau membuat setan terbang keluar hidung Anda . Sejauh menyangkut bahasa C ++, apa pun mungkin terjadi. Secara praktis, ini berarti Anda memiliki bug yang tidak dapat diperbaiki. Jika ini terjadi, Anda tidak dapat mempercayai apa pun tentang aplikasi Anda (karena salah satu efek dari perilaku tidak terdefinisi ini mungkin saja mengacaukan memori yang digunakan oleh aplikasi Anda lainnya). Tidak perlu konsisten, jadi menjalankan program dua kali mungkin memberikan hasil yang berbeda. Ini mungkin tergantung pada fase bulan, warna kemeja yang Anda kenakan, atau hal lainnya.

  • Perilaku tidak ditentukan berarti bahwa program harus melakukan sesuatu yang waras dan konsisten, tetapi tidak diwajibkan untuk mendokumentasikannya .

  • Perilaku yang ditentukan implementasi mirip dengan yang tidak ditentukan, tetapi juga harus didokumentasikan oleh penulis kompilator. Contoh dari ini adalah hasil dari a reinterpret_cast. biasanya , ini hanya mengubah jenis penunjuk, tanpa mengubah alamat, tetapi pemetaan sebenarnya ditentukan oleh implementasi, sehingga kompiler dapat memetakan ke alamat yang sama sekali berbeda, selama ia mendokumentasikan pilihan ini. Contoh lainnya adalah ukuran sebuah int. Standar C ++ tidak peduli apakah itu 2, 4 atau 8 byte, tetapi harus didokumentasikan oleh kompilator

Tetapi yang umum untuk semua ini adalah mereka sebaiknya dihindari. Jika memungkinkan, pertahankan perilaku yang 100% ditentukan oleh standar C ++ itu sendiri. Dengan begitu, Anda dijamin mudah dibawa.

Anda juga sering harus mengandalkan beberapa perilaku yang ditentukan implementasi. Ini mungkin tidak dapat dihindari, tetapi Anda harus tetap memperhatikannya, dan berhati-hatilah karena Anda mengandalkan sesuatu yang dapat berubah di antara kompiler yang berbeda.

Sebaliknya, perilaku tidak terdefinisi harus selalu dihindari. Secara umum, Anda harus berasumsi bahwa itu membuat program Anda meledak dengan satu atau lain cara.

jalf
sumber
1
UB harus dihindari jika Anda peduli dengan portabilitas . Implementasi tertentu dapat menentukan apa yang terjadi untuk perilaku tertentu yang tidak ditentukan, dan dalam beberapa kasus (terutama driver perangkat dan sistem tertanam yang lebih kecil) Anda perlu menggunakan hal-hal tersebut.
Jerry Coffin
3
@ Jerry: Enggak, UB harus dihindari jika seluruhnya undefined . Jika platform / implementasi / runtime / compiler memberikan jaminan lebih lanjut, Anda dapat mengandalkan perilaku tersebut dan kehilangan portabilitas. Tapi kemudian tidak lagi seperti tidak terdefinisi ... Namun, sebagian besar waktu, Anda tidak memiliki jaminan seperti itu, dan tidak terdefinisi hanya tidak terdefinisi, dan harus dihindari dengan cara apa pun.
jalf
"konsisten" mungkin merupakan deskripsi yang menyesatkan dari perilaku yang tidak ditentukan. Ini harus konsisten dengan konteks umum operasi, misalnya jika ekspresi memiliki "nilai yang tidak ditentukan" maka hasilnya harus berupa nilai, jika Anda menyimpannya maka nilai yang disimpan harus dibandingkan dengan dirinya sendiri, dan seterusnya. Tetapi hasil yang tidak ditentukan tidak perlu konsisten dari waktu ke waktu (keluaran yang sama untuk masukan yang sama jika Anda menjalankannya lagi), atau bahkan deterministik.
Steve Jessop
"tidak lagi cukup tidak terdefinisi" - ini persis seperti yang tidak ditentukan oleh standar , dan UB adalah arti singkat yang tidak ditentukan oleh standar. Dalam contoh Anda, ini ditentukan oleh implementasi. Dalam hal ini Anda dapat mengandalkan perilaku yang tidak ditentukan oleh standar atau implementasi, jika Anda telah memeriksa kode objek dan tidak berencana untuk mengkompilasi ulang lagi ;-)
Steve Jessop
"setelah itu harus dibandingkan dengan dirinya sendiri". Hmm, kecuali itu NaN. Bagaimanapun, itu harus memiliki perilaku apa pun yang dituntut dari tipenya.
Steve Jessop
8
  • IB: adalah implementasi perilaku yang ditentukan - kompilator harus mendokumentasikan apa yang dilakukannya. Melakukan >>operasi pada nilai negatif adalah contohnya.

  • UB: perilaku tidak terdefinisi - kompilator dapat melakukan apa pun, termasuk hanya menabrak atau memberikan hasil yang tidak dapat diprediksi. Dereferensi pointer nol termasuk dalam kategori ini, tetapi juga hal-hal yang lebih halus seperti aritmatika pointer yang berada di luar batas objek array.

Istilah terkait lainnya adalah 'perilaku tidak ditentukan'. Ini adalah jenis antara implementasi yang ditentukan dan perilaku yang tidak ditentukan. untuk perilaku yang tidak ditentukan, kompilator harus melakukan sesuatu sesuai dengan standar, tetapi pilihan mana yang diberikan standar itu terserah pada kompilator dan tidak perlu didefinisikan (atau bahkan konsisten). Hal-hal seperti urutan evaluasi sub-ekspresi termasuk dalam kategori ini. Kompilator dapat melakukan ini dalam urutan apa pun yang disukainya, dan dapat melakukannya secara berbeda dalam build yang berbeda atau bahkan dalam proses build yang sama berbeda (tidak mungkin, tetapi diizinkan).

Michael Burr
sumber
4

Versi singkatnya:

Perilaku yang ditentukan implementasi (IB): Diprogram dengan benar tetapi tidak dapat ditentukan *

Perilaku tidak terdefinisi (UB): Diprogram salah (mis. Bug !)

*) "tak tentu" sejauh menyangkut standar bahasa, itu tentu saja akan ditentukan pada platform tetap mana pun.

Kerrek SB
sumber
Jika standar menunjukkan bahwa suatu tindakan memanggil Perilaku yang Ditentukan Penerapan, implementasi diperlukan untuk menentukan perilaku yang konsisten yang dihasilkan dari tindakan itu. Sayangnya, tidak ada kategori perilaku yang penerapannya akan diperlukan untuk menentukan kemungkinan konsekuensi, tetapi tidak akan diminta untuk memiliki konsekuensi tertentu yang terjadi secara konsisten.
supercat