Saya mengerti bahwa simpan untuk keluar dari loop bersarang di loop; yang goto
pernyataan menghindari dan dicerca sebagai bug gaya rawan pemrograman, untuk tidak pernah digunakan.
Alt Text: "Neal Stephenson berpikir itu lucu untuk menamai labelnya 'dengo'"
Lihat komik aslinya di: http://xkcd.com/292/
Karena saya belajar ini sejak dini; Saya tidak benar-benar memiliki wawasan atau pengalaman tentang jenis bug apa yang goto
sebenarnya mengarah. Jadi apa yang kita bicarakan di sini:
- Ketidakstabilan?
- Kode tidak dapat dipertahankan atau tidak dapat dibaca?
- Kerentanan keamanan?
- Sesuatu yang lain sama sekali?
Bug seperti apa yang ditimbulkan oleh pernyataan "kebagian"? Apakah ada contoh signifikan secara historis?
Jawaban:
Ini cara untuk melihatnya. Saya belum melihat jawaban yang lain.
Ini tentang ruang lingkup. Salah satu pilar utama praktik pemrograman yang baik adalah menjaga ruang lingkup Anda tetap ketat. Anda membutuhkan ruang lingkup yang ketat karena Anda tidak memiliki kemampuan mental untuk mengawasi dan memahami lebih dari sekadar beberapa langkah logis. Jadi, Anda membuat blok kecil (masing-masing menjadi "satu hal") dan kemudian membangun dengan itu untuk membuat blok yang lebih besar yang menjadi satu hal, dan seterusnya. Ini menjaga hal-hal dapat dikelola dan dipahami.
Goto secara efektif mengembang cakupan logika Anda ke seluruh program. Ini pasti akan mengalahkan otak Anda untuk apa pun kecuali program terkecil yang hanya mencakup beberapa baris.
Jadi, Anda tidak akan dapat mengetahui apakah Anda melakukan kesalahan lagi karena terlalu banyak untuk menerima dan memeriksa kepala kecil Anda yang malang. Ini adalah masalah sebenarnya, bug hanyalah hasil yang mungkin.
sumber
Bukannya itu
goto
buruk dengan sendirinya. (Lagi pula, setiap instruksi lompatan di komputer adalah kebohongan.) Masalahnya adalah bahwa ada gaya manusia pemrograman yang pra-tanggal pemrograman terstruktur, apa yang bisa disebut pemrograman "diagram alur".Dalam pemrograman diagram alir (yang dipelajari oleh generasi saya, dan digunakan untuk program Apollo moon) Anda membuat diagram dengan blok untuk eksekusi pernyataan dan berlian untuk keputusan, dan Anda bisa menghubungkannya dengan garis yang mengarah ke mana-mana. (Disebut "kode spageti".)
Masalah dengan kode spaghetti adalah bahwa Anda, sang programmer, bisa "tahu" itu benar, tetapi bagaimana Anda bisa membuktikannya , kepada diri sendiri atau orang lain? Bahkan, itu mungkin sebenarnya memiliki potensi kelakuan buruk, dan pengetahuan Anda bahwa itu selalu benar bisa salah.
Seiring datang pemrograman terstruktur dengan blok awal-akhir, untuk, sementara, jika-lain, dan sebagainya. Ini memiliki keuntungan bahwa Anda masih bisa melakukan apa pun di dalamnya, tetapi jika Anda sama sekali berhati-hati, Anda bisa yakin kode Anda benar.
Tentu saja, orang masih dapat menulis kode spageti bahkan tanpa itu
goto
. Metode umum adalah menulis awhile(...) switch( iState ){...
, di mana kasus yang berbeda mengatur nilai yangiState
berbeda. Bahkan, dalam C atau C ++ orang dapat menulis makro untuk melakukan itu, dan beri namaGOTO
, jadi mengatakan Anda tidak menggunakangoto
adalah perbedaan tanpa perbedaan.Sebagai contoh bagaimana pembuktian kode dapat menghalangi tanpa batasan
goto
, sejak lama saya menemukan struktur kontrol yang berguna untuk antarmuka pengguna yang berubah secara dinamis. Saya menyebutnya eksekusi diferensial . Hal ini sepenuhnya Turing-universal, tetapi bukti kebenarannya tergantung pada pemrograman terstruktur murni - tidak adagoto
,return
,continue
,break
, atau pengecualian.sumber
Mengapa kebotakan berbahaya?
goto
tidak menyebabkan ketidakstabilan dengan sendirinya. Meskipun sekitar 100.000goto
detik, kernel Linux masih menjadi model stabilitas.goto
dengan sendirinya seharusnya tidak menyebabkan kerentanan keamanan. Namun dalam beberapa bahasa, mencampurnya dengantry
/catch
blok manajemen pengecualian dapat menyebabkan kerentanan seperti yang dijelaskan dalam rekomendasi CERT ini . Kompilator Mainstream menandai flag dan mencegah kesalahan seperti itu, tetapi sayangnya, kompiler yang lebih lama atau lebih eksotis tidak.goto
menyebabkan kode tidak terbaca dan tidak dapat dipelihara. Ini juga disebut kode spageti , karena, seperti pada piring spageti, sangat sulit untuk mengikuti aliran kontrol ketika ada terlalu banyak foto.Bahkan jika Anda berhasil menghindari kode spageti dan jika Anda hanya menggunakan beberapa foto, mereka masih memfasilitasi bug seperti dan sumber daya bocor:
goto
pernyataan, Anda mematahkan aliran langsung itu, dan mematahkan harapan. Misalnya, Anda mungkin tidak menyadari bahwa Anda masih harus membebaskan sumber daya.goto
tempat yang berbeda dapat mengirim Anda ke satu target goto. Jadi tidak jelas untuk mengetahui dengan pasti keadaan Anda saat mencapai tempat ini. Risiko membuat asumsi yang salah / tidak berdasar karenanya cukup besar.Informasi dan kutipan tambahan:
E.Dijkstra menulis esai awal tentang topik yang sudah ada di tahun 1968: " Go To Statement Dianggap Berbahaya "
Brian.W.Kernighan & Dennis.M.Ritchie menulis dalam bahasa pemrograman C:
James Gosling & Henry McGilton menulis di kertas putih lingkungan berbahasa Jawa 1995 :
Bjarne Stroustrup mendefinisikan goto dalam glosariumnya dalam istilah -istilah yang mengundang ini:
Kapan bisa digunakan?
Seperti K&R, saya tidak dogmatis tentang goto. Saya akui bahwa ada situasi di mana kebersamaan bisa memudahkan hidup seseorang.
Biasanya, dalam C, goto memungkinkan keluar loop bertingkat, atau penanganan kesalahan yang diperlukan untuk mencapai titik keluar yang sesuai yang membebaskan / membuka semua sumber daya yang dialokasikan sejauh ini (alokasi beberapa item secara berurutan berarti beberapa label). Artikel ini mengukur berbagai penggunaan goto di kernel Linux.
Secara pribadi saya lebih suka menghindarinya dan dalam 10 tahun C, saya menggunakan maksimal 10 foto. Saya lebih suka menggunakan nested
if
s, yang menurut saya lebih mudah dibaca. Ketika ini akan menyebabkan sarang terlalu dalam, saya akan memilih untuk menguraikan fungsi saya di bagian yang lebih kecil, atau menggunakan indikator boolean dalam kaskade. Kompilator pengoptimal hari ini cukup pintar untuk menghasilkan kode yang hampir sama dengan kode yang samagoto
.Penggunaan goto sangat tergantung pada bahasa:
Dalam C ++, penggunaan RAII yang tepat menyebabkan kompiler untuk secara otomatis menghancurkan objek yang keluar dari ruang lingkup, sehingga sumber daya / kunci tetap akan dibersihkan, dan tidak lagi membutuhkan goto.
Di Jawa tidak perlu untuk goto (lihat kutipan penulis Jawa di atas dan ini sangat baik jawaban Stack Overflow ): pengumpul sampah yang membersihkan kekacauan,
break
,continue
, dantry
/catch
penanganan eksepsi mencakup semua kasus di managoto
bisa membantu, tetapi dalam lebih aman dan lebih baik cara. Popularitas Java membuktikan bahwa pernyataan goto dapat dihindari dalam bahasa modern.Zoom pada goto SSL terkenal gagal kerentanan
Penafian Penting: mengingat diskusi yang sengit dalam komentar, saya ingin mengklarifikasi bahwa saya tidak berpura-pura bahwa pernyataan kebohongan adalah satu-satunya penyebab bug ini. Saya tidak berpura-pura bahwa tanpa goto tidak akan ada bug. Saya hanya ingin menunjukkan bahwa seorang goto dapat terlibat dalam bug serius.
Saya tidak tahu berapa banyak bug serius yang terkait
goto
dalam sejarah pemrograman: detail sering tidak dikomunikasikan. Namun ada bug Apple SSL terkenal yang melemahkan keamanan iOS. Pernyataan yang menyebabkan bug ini adalahgoto
pernyataan yang salah .Beberapa berpendapat bahwa akar penyebab bug itu bukan pernyataan goto itu sendiri, tetapi salinan / tempel yang salah, lekukan menyesatkan, hilang kawat gigi keriting di sekitar blok bersyarat, atau mungkin kebiasaan kerja pengembang. Saya tidak dapat mengkonfirmasi salah satu dari mereka: semua argumen ini adalah hipotesis dan interpretasi yang memungkinkan. Tidak ada yang benar-benar tahu. ( Sementara itu, hipotesis gabungan yang salah seperti yang disarankan seseorang dalam komentar tampaknya menjadi kandidat yang sangat baik mengingat beberapa inkonsistensi lekukan lain dalam fungsi yang sama ).
Satu-satunya fakta obyektif adalah bahwa duplikat
goto
menyebabkan keluar dari fungsi sebelum waktunya. Melihat kode tersebut, satu-satunya pernyataan tunggal yang dapat menyebabkan efek yang sama adalah pengembalian.Kesalahan dalam fungsi
SSLEncodeSignedServerKeyExchange()
dalam file ini :Memang kurung kurawal di sekitar blok bersyarat bisa mencegah bug:
itu akan menyebabkan kesalahan sintaks saat kompilasi (dan karenanya koreksi) atau ke goto tidak berbahaya yang berlebihan. Omong-omong, GCC 6 akan dapat menemukan kesalahan ini berkat peringatan opsional untuk mendeteksi lekukan yang tidak konsisten.
Tapi pertama-tama, semua foto ini bisa dihindari dengan kode yang lebih terstruktur. Jadi goto setidaknya secara tidak langsung menjadi penyebab bug ini. Setidaknya ada dua cara berbeda yang bisa menghindarinya:
Pendekatan 1: jika klausa atau bersarang
if
sAlih-alih menguji banyak kondisi untuk kesalahan secara berurutan, dan setiap kali mengirim ke
fail
label jika ada masalah, orang bisa memilih untuk mengeksekusi operasi kriptografi dalamif
pernyataan-yang hanya akan melakukannya jika tidak ada pra-kondisi yang salah:Pendekatan 2: gunakan akumulator kesalahan
Pendekatan ini didasarkan pada kenyataan bahwa hampir semua pernyataan di sini memanggil beberapa fungsi untuk menetapkan
err
kode kesalahan, dan mengeksekusi sisa kode hanya jikaerr
0 (yaitu, fungsi dieksekusi tanpa kesalahan). Alternatif aman dan mudah dibaca adalah:Di sini, tidak ada goto tunggal: tidak ada risiko untuk melompat dengan cepat ke titik keluar kegagalan. Dan secara visual akan mudah menemukan garis yang tidak selaras atau terlupakan
ok &&
.Konstruk ini lebih kompak. Ini didasarkan pada fakta bahwa dalam C, bagian kedua dari logika dan (
&&
) dievaluasi hanya jika bagian pertama benar. Bahkan, assembler yang dihasilkan oleh kompiler pengoptimalisasi hampir setara dengan kode asli dengan gotos: Pengoptimal mendeteksi dengan sangat baik rantai kondisi dan menghasilkan kode, yang pada awalnya nilai pengembalian bukan nol melompat ke akhir ( bukti online ).Anda bahkan bisa membayangkan pemeriksaan konsistensi di akhir fungsi yang bisa selama fase pengujian mengidentifikasi ketidakcocokan antara flag ok dan kode kesalahan.
Kesalahan seperti itu secara
==0
tidak sengaja diganti dengan!=0
kesalahan konektor atau logis akan dengan mudah terlihat selama fase debugging.Seperti yang dikatakan: Saya tidak berpura-pura bahwa konstruksi alternatif akan menghindari bug. Saya hanya ingin mengatakan bahwa mereka dapat membuat bug lebih sulit terjadi.
sumber
goto
dalamif
pernyataan tanpa tanda kurung . Tetapi jika Anda menyarankan bahwa menghindargoto
akan membuat kode Anda kebal terhadap efek garis yang diduplikasi secara acak, saya punya berita buruk untuk Anda.if
pernyataan? Waktu yang menyenangkan. :)Artikel Dijkstra yang terkenal ditulis pada saat beberapa bahasa pemrograman benar-benar mampu membuat subrutin yang memiliki banyak titik masuk dan keluar. Dengan kata lain, Anda dapat benar-benar melompat ke tengah-tengah suatu fungsi, dan melompat keluar di sembarang tempat di dalam fungsi tersebut, tanpa benar-benar memanggil fungsi itu atau kembali darinya dengan cara konvensional. Itu masih berlaku untuk bahasa assembly. Tidak ada yang pernah berpendapat bahwa pendekatan semacam itu lebih unggul daripada metode terstruktur dalam menulis perangkat lunak yang sekarang kita gunakan.
Dalam kebanyakan bahasa pemrograman modern, fungsi sangat spesifik didefinisikan dengan satu entri dan satu titik keluar. Titik masuk adalah tempat Anda menentukan parameter ke fungsi dan memanggilnya, dan titik keluar adalah tempat Anda mengembalikan nilai yang dihasilkan dan melanjutkan eksekusi pada instruksi mengikuti panggilan fungsi asli.
Dalam fungsi itu, Anda harus dapat melakukan apa pun yang Anda inginkan, dengan alasan. Jika menempatkan satu atau dua goto dalam fungsi membuatnya lebih jelas atau meningkatkan kecepatan Anda, mengapa tidak? Inti dari suatu fungsi adalah menyita sedikit fungsionalitas yang terdefinisi dengan jelas, sehingga Anda tidak perlu memikirkan cara kerjanya secara internal lagi. Setelah ditulis, Anda cukup menggunakannya.
Dan ya, Anda dapat memiliki beberapa pernyataan pengembalian di dalam suatu fungsi; masih selalu ada satu tempat di fungsi yang tepat dari mana Anda kembali (sisi belakang fungsi, pada dasarnya). Sama sekali tidak sama dengan melompat keluar dari suatu fungsi dengan kebotakan sebelum ia memiliki kesempatan untuk kembali dengan benar.
Jadi ini bukan tentang menggunakan goto. Ini tentang menghindari pelecehan mereka. Semua orang setuju bahwa Anda dapat membuat program yang sangat berbelit-belit menggunakan gotos, tetapi Anda juga dapat melakukan hal yang sama dengan menyalahgunakan fungsi-fungsi (hanya jauh lebih mudah untuk menyalahgunakan gotos).
Untuk apa nilainya, sejak saya lulus dari program BASIC garis-nomor-gaya untuk pemrograman terstruktur menggunakan bahasa Pascal dan curly-brace, saya tidak pernah menggunakan goto. Satu-satunya waktu saya tergoda untuk menggunakan salah satunya adalah melakukan keluar awal dari loop bersarang (dalam bahasa yang tidak mendukung keluar awal multi-level dari loop), tetapi saya biasanya dapat menemukan cara lain yang lebih bersih.
sumber
Saya biasa menggunakan
goto
pernyataan ketika menulis program BASIC sebagai seorang anak sebagai cara sederhana untuk mendapatkan dan sementara loop (Commodore 64 BASIC tidak memiliki while-loop, dan saya terlalu tidak matang untuk belajar sintaksis yang tepat dan penggunaan for-loop ). Kode saya sering sepele, tetapi bug loop apa pun dapat langsung dikaitkan dengan penggunaan goto.Saya sekarang menggunakan terutama Python, bahasa pemrograman tingkat tinggi yang telah menentukan itu tidak perlu untuk goto.
Ketika Edsger Dijkstra menyatakan "Goto dianggap berbahaya" pada tahun 1968 ia tidak memberikan beberapa contoh di mana bug terkait dapat disalahkan pada goto, melainkan, ia menyatakan bahwa
goto
tidak perlu untuk bahasa tingkat yang lebih tinggi dan bahwa itu harus dihindari demi apa kami mempertimbangkan aliran kontrol normal hari ini: loop dan kondisional. Kata-katanya:Dia mungkin memiliki banyak sekali contoh bug dari setiap kali dia mendebug kode
goto
di dalamnya. Tetapi makalahnya adalah pernyataan posisi umum yang didukung oleh bukti yanggoto
tidak perlu untuk bahasa tingkat yang lebih tinggi. Bug umum adalah bahwa Anda mungkin tidak memiliki kemampuan untuk menganalisis secara statis kode yang dimaksud.Kode jauh lebih sulit untuk dianalisis secara statis dengan
goto
pernyataan, terutama jika Anda melompat kembali dalam aliran kontrol Anda (yang dulu saya lakukan) atau ke bagian kode yang tidak terkait. Kode dapat dan ditulis dengan cara ini. Itu dilakukan untuk sangat mengoptimalkan sumber daya komputasi yang sangat langka dan dengan demikian arsitektur mesin.Contoh Apokrifa
Ada program blackjack yang ditemukan oleh seorang pengelola untuk dioptimalkan dengan sangat elegan tetapi juga tidak mungkin baginya untuk "memperbaiki" karena sifat kode. Itu diprogram dalam kode mesin yang sangat bergantung pada gotos - jadi saya pikir cerita ini cukup relevan. Ini adalah contoh kanonik terbaik yang dapat saya pikirkan.
Contoh Konter
Namun, sumber C dari CPython (implementasi Python yang paling umum dan referensi) menggunakan
goto
pernyataan untuk efek besar. Mereka digunakan untuk memotong aliran kontrol yang tidak relevan di dalam fungsi untuk sampai ke akhir fungsi, membuat fungsi lebih efisien tanpa kehilangan keterbacaan. Ini menghormati salah satu cita-cita pemrograman terstruktur - untuk memiliki satu titik keluar untuk fungsi.Sebagai catatan, saya menemukan contoh-counter ini cukup mudah untuk dianalisis secara statis.
sumber
Ketika wigwam adalah seni arsitektur saat ini, pembangun mereka tidak diragukan lagi dapat memberikan saran praktis mengenai pembuatan wigwam, cara membiarkan asap keluar, dan sebagainya. Untungnya, pembangun saat ini mungkin bisa melupakan sebagian besar saran itu.
Ketika kereta kuda itu adalah seni transportasi saat ini, pengemudi mereka pasti bisa memberi Anda nasihat praktis tentang kuda-kuda kereta kuda, cara mempertahankan diri dari para perampok, dan sebagainya. Untungnya, pengendara saat ini dapat melupakan sebagian besar saran itu juga.
Ketika kartu berlubang adalah seni pemrograman saat ini, para praktisi mereka juga dapat memberi Anda saran praktis tentang pengaturan kartu, cara menghitung angka, dan sebagainya. Saya tidak yakin saran itu sangat relevan saat ini.
Apakah Anda cukup tua untuk mengetahui ungkapan "ke nomor pernyataan" ? Anda tidak perlu mengetahuinya, tetapi jika tidak, maka Anda tidak terbiasa dengan konteks historis di mana peringatan terhadapnya
goto
pada dasarnya relevan.Peringatan terhadap
goto
tidak sangat relevan hari ini. Dengan pelatihan dasar saat / untuk loop dan panggilan fungsi, Anda bahkan tidak akan berpikir untuk mengeluarkannyagoto
sesering mungkin. Ketika Anda memikirkannya, Anda mungkin punya alasan, jadi silakan saja.Tapi bisakah
goto
pernyataan itu tidak disalahgunakan?Jawaban: tentu saja, ini dapat disalahgunakan, tetapi penyalahgunaannya merupakan masalah yang sangat kecil dalam rekayasa perangkat lunak dibandingkan dengan jauh, kesalahan yang jauh lebih umum seperti menggunakan variabel di mana konstanta akan melayani, atau seperti pemrograman cut-and-paste (jika tidak dikenal sebagai pengabaian terhadap refactor). Saya ragu Anda dalam banyak bahaya. Kecuali jika Anda menggunakan
longjmp
atau mentransfer kontrol ke kode yang jauh, jika Anda berpikir untuk menggunakangoto
atau Anda hanya ingin mencobanya untuk bersenang-senang, silakan. Kamu akan baik-baik saja.Anda mungkin memperhatikan kurangnya cerita-cerita horor terbaru yang
goto
menjadi penjahat. Sebagian besar atau semua kisah ini tampaknya berusia 30 atau 40 tahun. Anda berdiri di tanah yang kokoh jika Anda menganggap cerita-cerita itu sebagian besar sudah usang.sumber
Untuk menambahkan satu hal ke jawaban luar biasa lainnya, dengan
goto
pernyataan, mungkin sulit untuk mengatakan dengan tepat bagaimana Anda sampai ke tempat tertentu dalam program. Anda dapat mengetahui bahwa pengecualian terjadi pada beberapa baris tertentu tetapi jika adagoto
dalam kode tidak ada cara untuk mengetahui pernyataan apa yang dieksekusi untuk menghasilkan pengecualian ini yang menyebabkan keadaan tanpa mencari keseluruhan program. Tidak ada tumpukan panggilan dan tidak ada aliran visual. Ada kemungkinan bahwa ada pernyataan 1000 baris yang menempatkan Anda dalam kondisi buruk mengeksekusigoto
ke baris yang menimbulkan pengecualian.sumber
On Error Goto errh
, Anda bisa menggunakanResume
untuk mencoba lagi,Resume Next
untuk melewati garis yang menyinggung, danErl
untuk mengetahui baris mana itu (jika Anda menggunakan nomor baris).Resume
akan menjalankan kembali fungsi itu dari awal, danResume Next
akan melewati semua fungsi yang belum.On Error Goto 0
dan secara manual Debug.Resume
dimaksudkan untuk digunakan setelah memeriksaErr.Number
dan melakukan penyesuaian yang diperlukan.goto
hanya bekerja dengan garis berlabel, yang tampaknya telah digantikan oleh loop berlabel .goto lebih sulit bagi manusia untuk beralasan daripada bentuk lain dari kontrol aliran.
Memprogram kode yang benar itu sulit. Menulis program yang benar itu sulit, menentukan apakah program itu benar itu sulit, membuktikan bahwa program itu benar itu sulit.
Mendapatkan kode untuk melakukan apa yang Anda inginkan secara samar-samar itu mudah dibandingkan dengan segala sesuatu tentang pemrograman.
goto memecahkan beberapa program dengan mendapatkan kode untuk melakukan apa yang Anda inginkan. Ini tidak membantu membuat pengecekan kebenaran lebih mudah, sementara alternatifnya sering dilakukan.
Ada gaya pemrograman di mana goto adalah solusi yang tepat. Bahkan ada gaya pemrograman di mana saudara kembarnya yang jahat, datang dari, adalah solusi yang tepat. Dalam kedua kasus ini, sangat hati-hati harus dilakukan untuk memastikan Anda menggunakannya dalam pola yang dimengerti, dan banyak manual memeriksa bahwa Anda tidak melakukan sesuatu yang sulit untuk memastikan kebenaran dengan itu.
Sebagai contoh, ada fitur dari beberapa bahasa yang disebut coroutine. Coroutine adalah utas tanpa utas; negara eksekusi tanpa utas untuk menjalankannya. Anda dapat meminta mereka untuk mengeksekusi, dan mereka dapat menjalankan sebagian dari diri mereka sendiri dan kemudian menangguhkan diri mereka sendiri, menyerahkan kembali kontrol aliran.
Coroutine "Dangkal" dalam bahasa tanpa dukungan coroutine (seperti C ++ pra-C ++ 20 dan C) dimungkinkan menggunakan campuran gotos dan manajemen keadaan manual. Coroutine "Dalam" dapat dilakukan dengan menggunakan
setjmp
danlongjmp
fungsi C.Ada kasus di mana coroutine sangat berguna sehingga menulisnya secara manual dan hati-hati tidak sia-sia.
Dalam kasus C ++, mereka ditemukan cukup berguna sehingga mereka memperluas bahasa untuk mendukung mereka. The
goto
s dan manajemen negara pengguna sedang tersembunyi di balik lapisan abstraksi biaya nol, memungkinkan programmer untuk menulis mereka tanpa kesulitan karena harus membuktikan kekacauan mereka dari goto,void**
s, konstruksi manual / kehancuran negara, dll benar.Goto disembunyikan di balik abstraksi tingkat yang lebih tinggi, seperti
while
ataufor
atauif
atauswitch
. Abstraksi tingkat tinggi itu lebih mudah dibuktikan dengan benar dan diperiksa.Jika bahasa tersebut hilang beberapa dari mereka (seperti beberapa bahasa modern hilang coroutine), baik pincang bersama dengan pola yang tidak sesuai dengan masalah, atau menggunakan goto, menjadi alternatif Anda.
Membuat komputer secara samar melakukan apa yang Anda inginkan dalam kasus-kasus umum adalah mudah . Menulis kode yang andal dan tangguh itu sulit . Goto membantu yang pertama jauh lebih banyak daripada membantu yang kedua; maka "goto dianggap berbahaya", karena itu adalah tanda kode "bekerja" dangkal dengan yang dalam dan sulit untuk melacak bug. Dengan upaya yang cukup Anda masih bisa membuat kode dengan "goto" andal kuat, sehingga memegang aturan sebagai absolut itu salah; tetapi sebagai patokan, itu bagus.
sumber
longjmp
hanya legal di C untuk melepaskan tumpukan kembali kesetjmp
dalam fungsi induk. (Seperti memecah beberapa level sarang, tetapi untuk pemanggilan fungsi alih-alih loop).longjjmp
ke konteks darisetjmp
selesai dalam fungsi yang telah kembali tidak sah (dan saya curiga tidak akan bekerja dalam praktik dalam banyak kasus). Saya tidak akrab dengan rutinitas bersama, tetapi dari uraian Anda tentang rutinitas serupa dengan utas ruang pengguna, saya pikir itu akan membutuhkan tumpukannya sendiri dan juga konteks simpanan-register, danlongjmp
hanya memberi Anda daftar Hemat, bukan tumpukan yang terpisah.Lihatlah kode ini, dari http://www-personal.umich.edu/~axe/research/Software/CC/CC2/TourExec1.1.f.html yang sebenarnya merupakan bagian dari simulasi Dilema Tahanan yang besar. Jika Anda telah melihat kode FORTRAN atau BASIC lama, Anda akan menyadari bahwa itu tidak biasa.
Ada banyak masalah di sini yang melampaui pernyataan GOTO di sini; Jujur saya pikir pernyataan GOTO itu sedikit kambing hitam. Tetapi aliran kontrol sama sekali tidak jelas di sini, dan kode dicampur bersama dengan cara yang membuatnya sangat tidak jelas apa yang terjadi. Bahkan tanpa menambahkan komentar atau menggunakan nama variabel yang lebih baik, mengubahnya ke struktur blok tanpa GOTO akan membuatnya lebih mudah untuk dibaca dan diikuti.
sumber
Salah satu prinsip pemrograman terpelihara adalah enkapsulasi . Intinya adalah Anda berinteraksi dengan modul / rutin / subrutin / komponen / objek dengan menggunakan antarmuka yang ditentukan, dan hanya antarmuka itu, dan hasilnya akan dapat diprediksi (dengan asumsi bahwa unit tersebut diuji secara efektif).
Dalam satu unit kode, prinsip yang sama berlaku. Jika Anda secara konsisten menerapkan pemrograman terstruktur atau prinsip-prinsip pemrograman berorientasi objek, Anda tidak akan:
Beberapa gejala yang lebih umum dari kesalahan pemrosesan ini termasuk kebocoran memori, penimbunan memori, overflow pointer, crash, catatan data tidak lengkap, rekam add / chg / hapus pengecualian, kesalahan halaman memori, dan sebagainya.
Manifestasi yang dapat diamati pengguna dari masalah ini termasuk penguncian antarmuka pengguna, kinerja yang secara bertahap menurun, catatan data yang tidak lengkap, ketidakmampuan untuk memulai atau menyelesaikan transaksi, data yang rusak, pemadaman jaringan, pemadaman listrik, kegagalan sistem tertanam (dari hilangnya kendali rudal) hilangnya pelacakan dan kemampuan kontrol dalam sistem kontrol lalu lintas udara), kegagalan waktu, dan sebagainya. Katalog ini sangat luas.
sumber
goto
satu kali pun. :)goto berbahaya karena biasanya digunakan di tempat yang tidak diperlukan. Menggunakan apa pun yang tidak diperlukan itu berbahaya, tetapi terutama kebagian . Jika Anda google Anda akan menemukan banyak kesalahan di sekitar disebabkan oleh goto, ini bukan alasan untuk tidak menggunakannya (bug selalu terjadi ketika Anda menggunakan fitur bahasa karena itu intrinsik dalam pemrograman), tetapi beberapa dari mereka jelas sangat terkait untuk penggunaan goto .
Alasan menggunakan / tidak menggunakan goto :
Jika Anda memerlukan loop, Anda harus menggunakan
while
ataufor
.Jika Anda perlu melakukan lompatan bersyarat, gunakan
if/then/else
Jika Anda memerlukan prosedur, panggil fungsi / metode.
Jika Anda perlu keluar dari suatu fungsi, cukup
return
.Saya dapat mengandalkan jari-jari saya tempat-tempat di mana saya telah melihat
goto
digunakan dan digunakan dengan benar.Di libKTX ada fungsi yang memiliki kode berikut
Sekarang di tempat
goto
ini berguna karena bahasanya adalah C:Use case ini berguna karena dalam C kita tidak memiliki kelas, jadi cara paling sederhana untuk membersihkan adalah menggunakan a
goto
.Jika kami memiliki kode yang sama dalam C ++ tidak perlu lagi untuk goto:
Jenis bug apa yang dapat menyebabkannya? Apa pun. Loop tak terbatas, urutan eksekusi salah, tumpukan sekrup ..
Kasing terdokumentasi adalah kerentanan dalam SSL yang memungkinkan Manusia dalam serangan tengah yang disebabkan oleh penggunaan goto yang salah: inilah artikelnya
Itu kesalahan ketik, tetapi tidak diketahui untuk sementara waktu, jika kode disusun dengan cara lain, diuji dengan benar kesalahan seperti itu tidak mungkin terjadi.
sumber