“Goto” ifadeleri ne tür hatalara yol açar? Tarihsel olarak önemli örnekler var mı?


103

Döngü içinde iç içe geçmiş döngüleri kırmanın tasarrufunu anlıyorum; Bu gotoifade asla kullanılmayacak şekilde hata eğilimli bir programlama stili olarak gözden geçirilir ve iptal edilir.

XKCD Alt Metin: "Neal Stephenson onun etiketleri 'dengo' isim sevimli olduğunu düşünüyor"
: orijinal komik bakın http://xkcd.com/292/

Çünkü bunu erken öğrendim; Gerçekten ne tür böceklerin gotoyol açtığı hakkında hiçbir fikrim ya da deneyimim yok. Peki, burada ne hakkında konuşuyoruz:

  • Kararsızlık?
  • Devam edilemez mi yoksa okunamaz kod mu?
  • Güvenlik açıkları?
  • Tamamen başka bir şey?

"Goto" ifadeleri aslında ne tür hatalara yol açıyor? Tarihsel olarak önemli örnekler var mı?


33
Dijkstra'nın bu konuyla ilgili orijinal kısa makalesini okudunuz mu? (Bu bir Evet / Hayır sorusu ve net bir anında "evet" dışında herhangi bir cevap bir "hayır" dır.)
John R. Strohm 24:16

2
Bir alarm çıkışının, feci bir başarısızlık meydana geldiğinde olduğunu sanıyorum. Asla geri dönmeyeceğin yer. Elektrik kesintisi gibi, kaybolan aygıtlar veya dosyalar. Bazı "hataya geçme" türleri ... Ama bence çoğu "neredeyse felaket" hatalarının bugünlerde "dene - yakala" yapılarıyla çözülebileceğini düşünüyorum.
Lenne

13
Hesaplanan GOTO'dan henüz kimse bahsetmedi. Dünya gençken, BASIC satır numaralarına sahipti. Aşağıdakileri yazabilirsiniz: 100 N = A * 100; GOTO N. Hata ayıklamayı dene :)
mcottle

7
@ JohnR.Strohm Dijkstra'nın makalesini okudum. 1968'de yazılmıştır ve anahtar ifadeleri ve işlevler gibi gelişmiş özellikleri içeren dillerde goto ihtiyacının azaltılacağını öne sürmektedir. Goto'nun ana akış kontrol yöntemi olduğu ve programdaki herhangi bir noktaya atlamak için kullanılabileceği dillere cevap olarak yazılmıştır. Bu yazı yazıldıktan sonra geliştirilen dillerde, örneğin, C ise, goto sadece aynı yığın çerçevesindeki yerlere atlayabilir ve genellikle sadece diğer seçenekler iyi çalışmadığında kullanılır. (devam ...)
Ray

10
(… devam) Puanları o zamanlar geçerliydi, fakat artık iyi bir fikir olup olmadığına bakılmaksızın artık alakalı değil. Bir şekilde veya başka bir şekilde tartışmak istiyorsak, modern dillerle ilgili tartışmalar yapılmalıdır. Bu arada, var sen Knuth'un "git Tablolar ile Yapılandırılmış Programlama" okuma?
Ray,

Yanıtlar:


2

İşte diğer cevaplarda henüz görmediğim bir şey var.

Kapsam hakkında. İyi programlama uygulamasının ana direklerinden biri kapsamınızı sıkı tutmaktır. Sıkı bir kapsama ihtiyacınız var, çünkü bir kaç mantıksal adımdan daha fazlasını denetleyebilecek ve anlayabilecek zihinsel bir yeteneğiniz yok. Böylece küçük bloklar yaratırsınız (her biri "bir şey olur") ve daha sonra bir blok haline gelen daha büyük bloklar oluşturmak için olanlarla inşa edersiniz. Bu, işleri yönetilebilir ve anlaşılabilir tutar.

Bir goto mantığınızın kapsamını tüm programa etkili bir şekilde şişirir. Bu, beyninizi, yalnızca birkaç satırlık en küçük programlar dışında herhangi biri için yeneceğinizden emin olabilir.

Böylece artık bir hata yapıp yapmadığınızı söyleyemeyeceksiniz, çünkü içeri girmek ve zavallı küçük kafanızı kontrol etmek için çok fazla şey var. Asıl sorun bu, böcekler sadece olası bir sonuçtur.


Yerel olmayan goto?
Deduplicator

thebrain.mcgill.ca/flash/capsules/experience_jaune03.html << İnsan zihni aynı anda ortalama 7 şeyi izleyebilir. Mantığınız genişleyen kapsamın takip edilmesi gereken daha birçok şey ekleyeceğinden, bu sınırlamayı oynar. Dolayısıyla, ortaya çıkacak olan böcek türleri muhtemelen ihmal ve unutkanlıktan kaynaklanmaktadır. Ayrıca, “kapsamınızı sıkı tutmak” konusunda genel olarak hafifletici bir strateji ve iyi uygulamalar sunarsınız. Gibi, bu cevabı kabul ediyorum. İyi iş Martin.
Akiva

1
Ne kadar serin?! 200'ün üzerinde oy kullandı, sadece 1 oyla!
Martin Maat

68

Bu gotokendi başına kötü değil . (Sonuçta, bir bilgisayardaki her atlama talimatı bir adımdır.) Sorun şu ki, yapılandırılmış programlamayı önceden belirleyen, "akış şeması" programlaması olarak adlandırılabilecek bir programlama tarzı var.

Akış şeması programlamasında (kuşağımın insanları öğrendi ve Apollo ay programı için kullanıldı), karar yürütme ifadeleri için bloklar ve kararlar için elmaslar ile bir diyagram çizdiniz ve onları her yere giden çizgilerle bağlayabilirsiniz. (Sözde "spagetti kodu".)

Spagetti koduyla ilgili sorun, programcının doğru olduğunu "bilmesi" olabilirdi, ancak bunu kendinize veya başka birine nasıl kanıtlayabilirsiniz ? Aslında, potansiyel olarak yanlış bir davranışa sahip olabilir ve bunun her zaman doğru olduğu bilginiz yanlış olabilir.

Boyunca , başka bir şey için, eğer öyleyse, başlangıç-bitiş bloklarıyla yapılandırılmış programlama geldi . Bunların içinde hala bir şey yapabilme avantajınız vardı, ancak dikkatli olsanız, kodunuzun doğru olduğundan emin olabilirsiniz.

Tabii ki, insanlar hala olmasa bile spagetti kodu yazabilirsiniz goto. Yaygın yöntem, while(...) switch( iState ){...farklı durumların iStatefarklı değerlere ayarladığı bir a yazmaktır . Aslında, C veya C ++ 'da, bunu yapmak için bir makro yazabilir ve onu adlandırabilir GOTO, bu yüzden kullanmadığınızı söylemek gotofarksız bir ayrımdır.

Kod kanıtlamanın sınırsız olarak nasıl önlenebileceğinin bir örneği olarak goto, uzun zaman önce dinamik olarak değişen kullanıcı arayüzleri için kullanışlı bir kontrol yapısına rastladım. Buna diferansiyel işlem dedim . Tamamen Turing-evrenseldir, ancak onun doğruluğu ispat saf yapısal programlama bağlıdır - hayır goto, return, continue, break, veya istisnalar.

görüntü tanımını buraya girin


49
Yapısal programlama onları yazmak için kullanılsa bile, en önemsiz program haricinde doğruluk kanıtlanamaz . Yalnızca güven seviyenizi artırabilirsiniz; yapılandırılmış programlama bunu başarır.
Robert Harvey

23
@MikeDunlavey: İlgili: "Yukarıdaki koddaki hatalara dikkat edin; yalnızca doğru olduğunu kanıtladım, denemedim." staff.fnwi.uva.nl/p.vanemdeboas/knuthnote.pdf
Mooing Duck 24:16 '

26
@RobertHarvey Doğruluk kanıtlarının sadece önemsiz programlar için pratik olduğu kesin değildir . Bununla birlikte, yapılandırılmış programlamadan daha özel araçlar gereklidir.
Mike Haskel

18
@ MSalters: Bu bir araştırma projesi. Böyle bir araştırma projesinin amacı onlar göstermektir olabilir onlar kaynaklara olsaydı doğrulanmış derleyici yazmak. Mevcut çalışmalarına bakarsanız, basitçe C'nin sonraki sürümlerini desteklemekle ilgilenmediklerini göreceksiniz, aksine kanıtlayabilecekleri doğruluk özelliklerini genişletmekle ilgileniyorlar. Ve bunun için, C90, C99, C11, Pascal, Fortran, Algol veya Plankalkül'ü destekleyip desteklemedikleri tamamen alakasızdır.
Jörg W Mittag

8
@martineau: Programcıların kötü ya da iyi olduğunu kabul ettiği bir sıraya düştüğü "bozon cümleleri" nden bıktım, çünkü yapmazlarsa oturdular. İşlerin daha temel sebepleri olmalı.
Mike Dunlavey 24:16

63

Neden tehlikelisin?

  • gotokendi başına kararsızlığa neden olmaz. Yaklaşık 100.000 gotosaniyeye rağmen , Linux çekirdeği hala bir istikrar modelidir.
  • gotokendi başına güvenlik açıklarına neden olmamalıdır. Ancak bazı dillerde, try/ catchistisna yönetim bloklarıyla karıştırılması , bu CERT tavsiyesinde açıklandığı gibi güvenlik açıklarına neden olabilir . Mainstream C ++ derleyicileri bu hataları işaretler ve önler, ancak ne yazık ki, eski veya daha fazla egzotik derleyiciler yok.
  • gotookunamayan ve sürdürülemez kodlara neden olur. Buna spagetti kodu da denir , çünkü spagetti tabağında olduğu gibi çok fazla goto olduğunda kontrol akışını takip etmek çok zordur.

Spagetti kodundan kaçınmayı başarabilseniz ve sadece birkaç tane goto kullanıyorsanız bile, bunlar gibi kaynakları ve sızıntıyı kolaylaştırır:

  • Açık programlanmış bloklar ve döngüler veya anahtarlarla yapı programlamayı kullanan kodun izlenmesi kolaydır; kontrol akışı çok tahmin edilebilir. Bu nedenle değişmezlere saygı duyulmasını sağlamak daha kolaydır.
  • Bir gotoaçıklama ile, bu basit akışı ve beklentileri kırarsınız. Örneğin, hala kaynakları serbest bırakmadığınızı fark etmeyebilirsiniz.
  • gotoFarklı yerlerdeki birçok kişi sizi tek bir hedef hedefe gönderebilir. Bu nedenle, bu yere ulaştığınızda içinde bulunduğunuz durumun kesin olarak bilinmesi açık değildir. Yanlış / temelsiz varsayımlarda bulunma riski bu nedenle oldukça büyüktür.

Ek bilgi ve teklifler:

C, sınırsızca kötüye kullanılabilir gotoifadeyi ve etiketlenecek etiketleri sağlar. Resmen gotohiçbir zaman gerekli değildir ve pratikte hemen hemen her zaman onsuz kod yazmak kolaydır. (...)
Yine de, insanın bir yer bulabileceği birkaç durum önereceğiz. En yaygın kullanım, derhal iç içe geçmiş bazı yapılarda işlemden vazgeçmek, örneğin iki döngüden bir kerede çıkmak. (...)
Her ne kadar konu hakkında dogmatik olmasak da, ifadelerin hiç olmadığı kadar az kullanılması gerektiği görülüyor .

  • James Gosling ve Henry McGilton 1995 Java dili ortamı beyaz bülteninde yazdı :

    Daha Fazla Goto İfadesi Yok
    Java'nın hiç bir ifadesi yoktur. Çalışmalar goto'nun (yanlış) basitçe “çünkü orada” olduğundan daha sık kullanıldığını göstermiştir. Goto'yu ortadan kaldırmak, dilin sadeleştirilmesine yol açtı (...) Yaklaşık 100.000 C kod satırı üzerinde yapılan çalışmalar, goto ifadelerinin kabaca yüzde 90'ının yalnızca yuvalanmış ilmeklerden çıkma etkisini elde etmek için kullanıldığını belirledi. Yukarıda da değinildiği gibi, çok seviyeli kırılma ve devam etme ifadeleri için ihtiyaçların çoğunu ortadan kaldırmaya devam edin.

  • Bjarne Stroustrup , sözlüğünde goto'yu şu davetkar terimlerle tanımlar:

    Goto - rezil goto. Öncelikle makinede üretilen C ++ kodunda faydalı.

Ne zaman kullanılabilir?

K & R gibi ben gotos hakkında dogmatik değilim. İnsanın hayatını kolaylaştıracağı durumlar olduğunu itiraf ediyorum.

Tipik olarak, C'de goto, çok seviyeli döngü çıkışına veya şimdiye kadar tahsis edilen tüm kaynakları serbest bırakan / kilidini açan uygun bir çıkış noktasına ulaşmayı gerektiren hata işlemlerine izin verir (sırayla birden fazla etiket, birden fazla etiket anlamına gelir). Bu makale , Linux çekirdeğindeki goto'nun farklı kullanımlarını ölçmektedir.

Şahsen bundan kaçınmayı tercih ediyorum ve 10 yılda C, maksimum 10 goto kullandım. ifSanırım daha okunaklı olduğunu düşündüğüm iç içe geçmeyi tercih ediyorum . Bu, çok derin bir yuvalamaya neden olduğunda, işlevimi daha küçük parçalara ayırmayı ya da kaskadda bir boolean göstergesi kullanmayı tercih ederim. Günümüzün optimize eden derleyicileri, aynı kodla neredeyse aynı kodu üretecek kadar akıllıdır goto.

Goto'nun kullanımı yoğun olarak dile bağlıdır:

  • C ++ 'da, RAII'nin doğru kullanılması derleyicinin kapsam dışına çıkan nesneleri otomatik olarak imha etmesine neden olur, böylece kaynaklar / kilit yine de temizlenecek ve artık gerçek bir ihtiyaç olmayacak.

  • Java'da hiçbir Goto ihtiyacı (Java'nın yukarıdaki yazar teklifi ve bunu görmek var mükemmel yığın taşması cevap ): karışıklık, temizler çöp toplayıcısı break, continueve try/ catchistisna işleme tüm dava kapsayacak gotoyararlı olabilir, ama içinde daha güvenli ve iyi tavır. Java’nın popülaritesi, modern bir dilde deyimden kaçınılabileceğini kanıtlıyor.

Ünlü SSL goto fail güvenlik açığı üzerinde yakınlaştırma

Önemli Sorumluluk Reddi: yorumlardaki şiddetli tartışmalar ışığında, goto ifadesinin bu hatanın tek nedeni olduğunu iddia etmediğimi açıklığa kavuşturmak istiyorum. Yapmadan hiçbir hata olmayacağını sanmıyorum. Sadece bir goto'nun ciddi bir böceğe karıştığını göstermek istiyorum.

gotoProgramlama tarihinde kaç tane ciddi hatanın bulunduğunu bilmiyorum : ayrıntılar genellikle iletilmez. Ancak iOS'un güvenliğini zayıflatan ünlü bir Apple SSL hatası vardı. Bu hataya yol açan gotoifade yanlış bir ifadeydi.

Bazıları, hatanın kök nedeninin kendi başındaki ifade ifadesi değil, hatalı bir kopyala / yapıştır, yanıltıcı bir girinti, koşullu bloğun etrafındaki kıvrık kaşlı ayraçlar veya geliştiricinin çalışma alışkanlıkları olduğunu iddia ediyor. Hiçbirini onaylayamıyorum: tüm bu argümanlar olası hipotezler ve yorumlardır. Gerçekten kimse bilmiyor. ( bu arada, yorumlarda birinin önerdiği gibi yanlış giden bir birleştirme hipotezi, aynı fonksiyondaki diğer girinti tutarsızlıkları açısından çok iyi bir aday gibi görünüyor ).

Tek nesnel gerçek, kopyalananın gotoişlevden erken çıkmasına yol açtığıdır. Kurallara bakıldığında, aynı etkiye neden olabilecek diğer tek açıklama bir dönüş olacaktır.

Hata işlevinde olduğu SSLEncodeSignedServerKeyExchange()içinde bu dosya :

    if ((err = ReadyHash(&SSLHashSHA1, &hashCtx)) != 0)
        goto fail;
    if ((err =...) !=0)
        goto fail;
    if ((err = SSLHashSHA1.update(&hashCtx, &signedParams)) != 0)
        goto fail;
        goto fail;  // <====OUCH: INDENTATION MISLEADS: THIS IS UNCONDITIONDAL!!
    if (...)
        goto fail;

    ... // Do some cryptographic operations here

fail:
    ... // Free resources to process error

Nitekim, koşullu bloğun etrafındaki küme parantezleri hatayı önleyebilirdi:
ya derleme sırasında bir sözdizimi hatası (ve dolayısıyla bir düzeltme) ya da yedekli zararsız bir başa çıkma yol açardı. Bu arada, GCC 6 tutarsız girintileri tespit etmek için isteğe bağlı uyarısı sayesinde bu hataları tespit edebilecektir.

Fakat ilk etapta, tüm bu gotos daha yapısal bir kodla önlenebilirdi. Yani goto en azından dolaylı olarak bu hatanın bir nedenidir. Bundan kaçınabilecek en az iki farklı yol var:

Yaklaşım 1: fıkra veya iç içe geçmişse ifs

Ardışık hata için birçok koşulu test etmek yerine ve failsorun olması durumunda bir etikete her gönderimde , kriptografik işlemlerin ifyalnızca yanlış bir ön koşul olmasaydı yapacak bir açıklamada yürütülmesi istenebilirdi:

    if ((err = ReadyHash(&SSLHashSHA1, &hashCtx)) == 0 &&
        (err = ...) == 0 ) &&
        (err = ReadyHash(&SSLHashSHA1, &hashCtx)) == 0) &&
        ...
        (err = ...) == 0 ) )
    {
         ... // Do some cryptographic operations here
    }
    ... // Free resources

Yaklaşım 2: bir hata biriktiricisi kullanın

Bu yaklaşım, buradaki hemen hemen tüm ifadelerin bir errhata kodu belirlemek için bazı işlevler çağırması ve kodun geri kalan kısmını yalnızca err0 olması durumunda yürütmesi (yani, hatasız çalıştırılan işlev) temeline dayanır . Güzel, güvenli ve okunabilir bir alternatif:

bool ok = true;
ok =  ok && (err = ReadyHash(&SSLHashSHA1, &hashCtx))) == 0;
ok =  ok && (err = NextFunction(...)) == 0;
...
ok =  ok && (err = ...) == 0;
... // Free resources

Burada tek bir goto yoktur: başarısızlık çıkış noktasına hızlıca atlamak için risk yoktur. Ve görsel olarak yanlış hizalanmış bir çizgiyi veya unutulmuş bir çizgiyi bulmak kolay olurdu ok &&.

Bu yapı daha kompakt. C'de bir mantığın ve ( &&) ikinci bölümünün sadece ilk bölüm geçerliyse değerlendirilmesi gerçeğine dayanmaktadır . Aslında, bir optimize edici derleyici tarafından üretilen montajcı, gotos'lu orijinal koda hemen hemen eşdeğerdir: Optimizer, koşul zincirini çok iyi algılar ve ilk boş olmayan geri dönüş değerinin sonuna ( çevrimiçi kanıt ) atlayan kod üretir .

Test aşamasında, tamam bayrağı ile hata kodu arasındaki uyuşmazlıkları tanımlayabilecek fonksiyonun sonunda bir tutarlılık kontrolü bile öngörebilirsiniz.

assert( (ok==false && err!=0) || (ok==true && err==0) );

Bu tür bir yanlışlıkların ==0yanlışlıkla ile değiştirilmesi !=0veya mantıksal bağlantı hatalarının kolayca ayıklama aşamasında tespit edilecektir.

Dediğim gibi: Alternatif yapıların herhangi bir hatadan kaçınılması gerektiğini iddia etmiyorum. Sadece, böceğin gerçekleşmesini zorlaştırabileceğini söylemek istiyorum.


34
Hayır, Apple Goto'nun başarısızlık hatası, if if ifadesinden sonra küme parantezlerini dahil etmemeye karar veren akıllı bir programcının neden oldu. :-) Böylece, bir sonraki bakım programcısı (veya aynı, aynı fark) ortaya çıktı ve yalnızca if ifadesi doğru olarak değerlendirildiğinde çalıştırılması gereken başka bir kod satırı eklediğinde, ifade her zaman çalıştırıldı. Bam, büyük bir güvenlik hatası olan "gitme başarısız" hatası. Ancak, esasen, bir goto ifadesinin kullanıldığı gerçeği ile ilgisi yoktu.
Craig

47
Apple "goto fail" hatası doğrudan kopyalanan bir kod satırından kaynaklanıyordu. Bu hatanın özel etkisi, bu çizginin, gotoayraçsız bir ififadenin içinde olmasından kaynaklandı . Ancak, kaçınmanın gotokodunuzu rastgele kopyalanan satırların etkilerine karşı bağışık hale getireceğini öne sürüyorsanız , size kötü haberlerim var.
immibis

12
Yan etki yoluyla bir deyimi yürütmek ve bir deyimden daha açık olduğunu iddia etmek için kısayol boolean operatörü davranışını kullanıyor ifmusunuz? Eğlenceli zamanlar. :)
Craig

38
Eğer "goto fail" yerine "fail = true" diye bir ifade olsaydı aynı şey olurdu.
gnasher729

15
Bu hata bir özensiz geliştirici o ne yaptığını dikkat ederek değil, değil neden oldu okuyarak kendi kod değişiklikleri. Ne fazla ne eksik. Tamam, belki de orada test sınavlarına girebilirsin.
Orbit'teki Hafiflik Yarışları

34

Ünlü Dijkstra makalesi, bazı programlama dillerinin aslında çoklu giriş ve çıkış noktalarına sahip alt yordamlar oluşturma yeteneğine sahip olduğu bir zamanda yazıldı . Başka bir deyişle, kelimenin tam anlamıyla bir işlevin ortasına atlayabilir ve işlevin içinde herhangi bir yere, o işlevin çağrılması ya da ondan geleneksel şekilde geri dönmeden atlayabilirsiniz. Bu hala assembly dili için geçerlidir. Hiç kimse böyle bir yaklaşımın şu anda kullandığımız yapısal yazılım yazma yönteminden daha üstün olduğunu iddia etmedi.

Çoğu modern programlama dilinde, fonksiyonlar özellikle bir giriş ve bir çıkış noktası ile tanımlanır . Giriş noktası, parametreleri işleve belirlediğiniz ve aradığınız yerdir ve çıkış noktası, sonuç değerini döndürdüğünüz ve orijinal işlev çağrısını izleyen talimatta çalışmaya devam ettiğiniz yerdir.

Bu fonksiyon dahilinde, ne istersen, mantıklı bir şekilde ne yapabileceğini yapmalısın. Fonksiyona bir ya da iki tane koymak, onu daha net hale getirir veya hızınızı arttırırsa, neden olmasın? Bir işlevin amacı, açıkça tanımlanmış bir işlevsellikten biraz saklanmaktır, böylece artık içsel olarak nasıl çalıştığını düşünmek zorunda kalmazsınız. Yazıldıktan sonra, sadece onu kullan.

Ve evet, bir fonksiyon içerisinde birden fazla return ifadesi olabilir; hala geri döndüğünüz uygun bir fonksiyonda daima bir yer vardır (işlevin arka tarafı, temel olarak). Bu, düzgün bir şekilde geri dönme şansı olmadan, bir goto olan bir fonksiyondan atlamakla aynı şey değildir.

görüntü tanımını buraya girin

Yani gerçekten goto's kullanmakla ilgili değil. İstismarlarından kaçınmakla ilgili. Herkes, gotos kullanarak çok karmaşık bir program yapabileceğinizi kabul eder, ancak aynı zamanda işlevleri kötüye kullanarak da yapabilirsiniz (gotoları kötüye kullanmak çok daha kolaydır).

Buna değecek bir şey yok. Pascal ve kaşlı ayraç dillerini kullanarak çizgi-tarzı BASIC programlarından yapılandırılmış programlamaya mezun olduğumdan beri, hiçbir zaman bir goto kullanmak zorunda kalmamıştım. Birini kullanmak için cazip olduğum tek zaman iç içe geçmiş bir döngüden erken bir çıkış yapmak (döngülerden çok düzeyli erken çıkışı desteklemeyen dillerde), ancak genellikle daha temiz olan başka bir yol bulabilirim.


2
Yorumlar uzun tartışmalar için değildir; bu konuşma sohbete taşındı .
maple_shaft

11

“Goto” ifadeleri ne tür hatalara yol açar? Tarihsel olarak önemli örnekler var mı?

Ben kullanmayı kullanılan gotoTEMEL while-döngüler yoktu basit bir yol olarak bir çocuk olarak TEMEL programları yazarken Commodore 64 (ve while döngüleri almak için ifadeler ve ben için-döngü doğru sözdizimini ve kullanımını öğrenmek için çok olgunlaşmamış oldu ). Kodum sık sık önemsizdi, ancak herhangi bir döngü hatası derhal goto kullanımıma atfedilebilirdi.

Şimdi öncelikle, artık ihtiyaç duymadığını belirleyen yüksek seviye bir programlama dili olan Python kullanıyorum.

Edsger Dijkstra ilan ettiğinde ilgili hatalar Goto suçladığı olabilir örneklerinden bir avuç vermedi 1968 yılında "Goto zararlı kabul", daha doğrusu, o beyan gotooldu üst düzey diller için gereksiz ve lehine kaçınılmalıdır bunun ne Bugün normal kontrol akışını düşünüyoruz: döngüler ve şartlamalar. Onun sözleri:

Dizginsiz kullanım halindeyken için süreç ilerleme tarif etmesi için koordinatlar anlamlı bir set bulmak çok zor olur hemen bir sonucu vardır.
[...] için devam bu haliyle açıklamada sadece çok ilkel olduğu; bir programın karmaşasını yapmak için çok fazla bir davetiye.

Muhtemelen kodunda hata ayıkladığı her zamandan hataların örnekleri vardı goto. Ancak makalesi, gotodaha yüksek seviyeli diller için gereksiz olan kanıtlarla desteklenen genelleştirilmiş bir pozisyon ifadesiydi . Genel hata, söz konusu kodu statik olarak analiz etme yeteneğiniz olmayabilir.

Kod goto, özellikle kontrol akışınıza (yaptığım) geri döndüğünüzde veya kodun ilgisiz bazı bölümlerine atlarsanız, ifadelerle statik olarak analiz etmek çok daha zordur . Kod bu şekilde yazılabilir ve yazılmıştır. Çok az bilgi işlem kaynağı ve dolayısıyla makinelerin mimarileri için yüksek düzeyde optimize etmek için yapıldı.

Kıyamet Örneği

Bir koruyucunun oldukça zarif bir şekilde optimize edilmiş olduğu, ancak kodun niteliği nedeniyle "düzeltmesi" imkansız olduğu bir blackjack programı vardı . Makine kodunda gotos'a büyük ölçüde bağlı olan programlanmış - bu yüzden bu hikayenin oldukça ilgili olduğunu düşünüyorum. Bu, aklıma gelen en iyi kanonik örnektir.

Bir Sayaç Örneği

Bununla birlikte, CPython'un C kaynağı (en yaygın ve referans Python uygulaması) gotoçok etkili olması için ifadeler kullanır . İşlevlerin sonuna ulaşmak için işlevlerin içindeki alakasız kontrol akışını atlamak, işlevleri okunabilirliği kaybetmeden daha verimli hale getirmek için kullanılırlar. Bu, yapılandırılmış programlamanın ideallerinden birine saygılıdır - işlevler için tek bir çıkış noktasına sahip olmak.

Kayıt için bu karşı örneği statik olarak analiz etmenin oldukça kolay olduğunu düşünüyorum.


5
Karşılaştığım "Mel'in Öyküsü", (1) her makine dili komutunun işleminden sonra bir adım attığı ve (2) ardışık bellek konumlarına bir dizi komut yerleştirmenin korkunç derecede yetersiz olduğu garip bir mimarideydi. Ve program derlenmiş bir dil değil, el ile en iyi duruma getirilmiş derlemede yazıldı.

@MilesRout Burada doğru olabileceğinizi düşünüyorum, ancak yapısal programlama hakkındaki wikipedia sayfası şöyle diyor: "Birçok dilde bulunan en yaygın sapma, bir alt programdan erken çıkış için bir return ifadesinin kullanılmasıdır. Bu, çoklu çıkış noktalarına neden olur. yapılandırılmış programlama için gereken tek çıkış noktası yerine. " - Bunun yanlış olduğunu mu söylüyorsun? Alıntı yapacak bir kaynağınız var mı?
Aaron Hall

@AaronHall Orijinal anlamı bu değil.
Miles Rout

11

Ne zaman wigwam güncel mimari sanat oldu, onların inşaatçılar şüphesiz bu kadar duman kaçmasına izin ve nasıl wigwams, inşası konusunda pratik öneriler ses verebilir. Neyse ki, bugünün inşaatçıları bu tavsiyenin çoğunu unutabilir.

Ne zaman posta arabası akım taşımalı sanattı, onların sürücüleri şüphesiz sen karşı savunmak için nasıl stagecoaches, atları ile ilgili pratik öneriler ses verebilir highwaymen, vb vb. Neyse ki, bugünün sürücüleri de bu tavsiyenin çoğunu unutabilir.

Ne zaman delikli kartlar geçerli programlama sanatı vardı, onların uygulayıcıları aynı şekilde bu kadar ilgili ifadeleri sayı ve nasıl, kartların organizasyonu konusunda pratik öneriler ses verebilir. Bu tavsiyenin bugün çok alakalı olduğundan emin değilim.

"Sayı cümlelerine" ifadesini bile bilecek kadar yaşlı mısınız ? Bunu bilmenize gerek yok, ancak bilmiyorsanız, o zaman aleyhindeki uyarının gototemelde ilgili olduğu tarihsel bağlamla aşina değilsiniz .

Karşı uyarı gotosadece bugün pek alakalı değil. Döngü / işlev çağrıları ve işlev çağrıları için temel eğitimle, çok sık yayınlamayı bile düşünmezsinizgoto . Bunu düşündüğünüzde, muhtemelen bir sebebiniz var, bu yüzden devam edin.

Ancak gotoifade kötüye kullanılamaz mı?

Cevap: elbette, kötüye kullanılabilir, ancak kötüye kullanılması, yazılım mühendisliğinde, bir sabitin hizmet edeceği bir değişken kullanmak veya kes ve yapıştır programlama gibi çok daha yaygın hatalara kıyasla oldukça küçük bir sorundur (aksi halde refaktör ihmali olarak bilinir). Tehlikede olduğunuzdan şüpheliyim. longjmpUzak kodlara kontrolü kullanmıyorsanız veya başka bir şekilde aktarmıyorsanız, a kullanmayı düşünüyorsanız gotoveya sadece eğlence için denemek istiyorsanız, devam edin. İyi olacaksın.

Kötü niyetli olan son korku hikayelerinin eksikliğini fark edebilirsiniz goto. Bu hikayelerin çoğu ya da tamamı 30 ya da 40 yaşında görünüyor. Bu hikayeleri çoğunlukla modası geçmiş görüyorsanız, sağlam zeminde durursunuz.


1
Görüyorum ki en az bir oy aldım. Bu beklenen bir şey. Daha fazla aşağı oy gelebilir. Buna rağmen, onlarca yıllık programlama deneyimi bana, bu örnekte, konvansiyonel cevabın yanlış olduğunu öğrettiğinde, geleneksel cevabı vermeyeceğim . Bu benim görüşüme göre, herhangi bir oranda. Sebeplerimi verdim. Okuyucu karar verebilir.
thb

1
Gönderiniz çok kötü, yorumlardan vazgeçemiyorum.
Pieter B

7

Bir şeyi diğer mükemmel cevaplara eklemek için, gotoifadelerle programda herhangi bir yere nasıl ulaştığınızı tam olarak söylemek zor olabilir. Belirli bir satırda bir istisna oluştuğunu biliyorsunuzdur, ancak gotokodda varsa, bu istisnayla sonuçlanan hangi ifadelerin programın tamamını aramadan duruma neden olduğunu söylemenin bir yolu yoktur. Çağrı yığını ve görsel akış yok. gotoBir istisna ortaya çıkaran çizgiye, sizi kötü bir duruma sokan 1000 satır ötede bir ifade olması mümkündür .


1
Visual Basic 6 ve VBA'da ağrılı hata işleme var, ancak kullanırsanız On Error Goto errh, Resumeyeniden denemek, Resume Nextrahatsız edici çizgiyi atlamak ve Erlhangi çizginin olduğunu bilmek için kullanabilirsiniz (satır numaraları kullanıyorsanız).
Cees Timmerman

@CeesTimmerman Visual Basic ile çok az şey yaptım, bunu bilmiyordum. Bununla ilgili bir yorum ekleyeceğim.
qfwfq

2
@CeesTimmerman: "Özgeçmiş" in VB6 semantiği, kendi hata bloğu olmayan bir alt rutinde bir hata meydana gelirse korkunçtur. Resumebu işlevi en baştan tekrar çalıştıracak ve fonksiyondaki Resume Nexthenüz her şeyi atlayacaktır.
supercat

2
@supercat Dediğim gibi, acı verici. Kesin çizgiyi bilmeniz gerekiyorsa, hepsini numaralandırmanız veya hata işlemeyi Hatalı On Error Goto 0ve manuel olarak Hata Ayıklama ile devre dışı bırakmanız gerekir . gerekli ayarlamaları Resumekontrol ettikten Err.Numberve kontrol ettikten sonra kullanılmalıdır .
Cees Timmerman

1
Modern bir dilde, gotosadece etiketli döngülerden önce görünen etiketli çizgilerle çalıştığını not etmeliyim .
Cees Timmerman

7

goto, insanlara, diğer akış kontrol biçimlerinden daha fazla neden göstermek zordur.

Doğru kodu programlamak zordur. Doğru programları yazmak zor, programların doğru olup olmadığını belirlemek zor, programları doğrulamak zor.

Programlama ile ilgili diğer her şeye kıyasla belirsiz bir şekilde istediğiniz şeyi yapmak için kod almak kolaydır.

Gitmek istediğin şeyi yapmak için bazı programları kod alarak çözer. Alternatiflerini sık sık yaparken, doğruluğu kontrol etmeyi kolaylaştırmaz.

Goto'nun uygun çözüm olduğu programlama stilleri vardır. Kötü ikizinin uygun çözüm olduğu programlama stilleri bile var. Her iki durumda da, anlaşılan bir düzende kullandığınızdan emin olmak için çok dikkatli olunmalı ve doğruluğunu sağlamak için zor bir şey yapmadığınız birçok manuel kontrol yapılmalıdır.

Örnek olarak, bazı dillerde koroutinler adı verilen bir özellik vardır. Korotinler dişsiz dişlerdir; çalıştırılacak iş parçacığı olmadan yürütme durumu. Onlardan çalışmalarını isteyebilir ve kendilerinin bir bölümünü yönetebilir ve daha sonra geri akış kontrolünü geri vererek kendilerini askıya alabilirler.

Coroutin desteği olmayan dillerde "sığ" coroutinler (C ++ pre-C ++ 20 ve C gibi) bir goto ve manuel durum yönetimi karışımı kullanılarak mümkündür. "Derin" coroutinler , C setjmpve longjmpfonksiyonlarını kullanarak yapılabilir .

Coroutinler çok elverişli olduğu durumlarda bunları elle ve dikkatlice yazmak buna değer.

C ++ 'da, dili desteklemek için dili genişletecekleri kadar faydalı bulunmuşlardır. gotoLer ve manuel devlet yönetimi bunları yazmak için programcılar izin veren bir sıfır maliyetli soyutlama katmanına arkasına gizlenmiş olan olmadan Goto, onların karmaşa kanıtlamak zorunda zorluk void**s, manuel inşaat / devletin imha, vb doğrudur.

Git gibi yüksek bir seviyede soyutlama arkasında gizli alır whileya forya ifya switch. Bu yüksek seviyeli soyutlamalar doğru ve kontrol kanıtlamak kolaydır.

Dil ise eksik (bazı modern diller coroutines eksik gibi) bazıları, ya problemi sığmayan bir desenle birlikte limpling veya goto ifadesi kullanarak, alternatifler olur.

Bir bilgisayarı sık karşılaşılan durumlarda ne yapmak istediğinizi belli bir şekilde yapması kolaydır . Güvenilir bir şekilde sağlam kod yazmak zordur . Goto, birincisine, ikincisinden daha çok yardım eder; Bu nedenle, "yüzeysel olarak" çalışmakta olan "kodun bir işareti olduğu için" zarar verici olarak kabul edilir ". Yeterince çabayla, hala güvenilir bir şekilde "goto" ile kod oluşturabilirsiniz, bu nedenle kuralını mutlak tutmak; Ancak, kural olarak, iyi bir kuraldır.


1
longjmpYığını setjmpbir üst işlevdeki bir geri çevirmek için yalnızca C'de yasaldır . (Birden çok iç içe geçme düzeyinden ayrılmak gibi, ancak döngüler yerine işlev çağrıları için). o zamandan beri geri dönen bir fonksiyonda yapılan longjjmpbir bağlamda setjmpyasal değildir (ve çoğu durumda pratikte işe yaramayacağından şüpheliyim). Yardımcı yordamlara aşina değilim, ancak kullanıcı alanı iş parçacığına benzer bir yardımcı yordam tanımlamanızdan, kendi yığınına ve kaydedilmiş bir kayıt içeriğine ihtiyaç duyacağını düşünüyorum, ve longjmpyalnızca size kayıt verir Tasarruf, ayrı bir yığın değil.
Peter Cordes

1
Oh, sadece googled olmalıydım: fanf.livejournal.com/105413.html , coroutinin çalışması için yığın alanı yapmayı açıklar. (Şüphelendiğim gibi, sadece setjmp / longjmp kullanmanız gerekir).
Peter Cordes

2
@PeterCordes: Uygulamaların, bir koroutin olarak kullanılmaya uygun bir çift jmp_buff çifti oluşturabilmesi için herhangi bir yol sağlaması gerekmez. Bazı uygulamalar, Standart'ın böyle bir yetenek sağlamasını gerektirmese de, kodun içinden bir kod oluşturabileceği bir yöntem belirtir. Çoğu durumda bir jmp_buff farklı derleyiciler arasında tutarlı davranması garanti edilmeyen bir opak yapı olacağından, "standart C" gibi tekniklere dayanan kodu tarif etmem.
supercat,

6

Aslında, büyük bir mahkumun Dilemma simülasyonunun bir parçası olan http://www-personal.umich.edu/~axe/research/Software/CC/CC2/TourExec1.1.f.html adresinden bu koda bir göz atın . Eski FORTRAN veya BASIC kodunu gördüyseniz, bunun alışılmadık olmadığını fark edeceksiniz.

C  Not nice rules in second round of tour (cut and pasted 7/15/93)
   FUNCTION K75R(J,M,K,L,R,JA)
C  BY P D HARRINGTON
C  TYPED BY JM 3/20/79
   DIMENSION HIST(4,2),ROW(4),COL(2),ID(2)
   K75R=JA       ! Added 7/32/93 to report own old value
   IF (M .EQ. 2) GOTO 25
   IF (M .GT. 1) GOTO 10
   DO 5 IA = 1,4
     DO 5 IB = 1,2
5  HIST(IA,IB) = 0

   IBURN = 0
   ID(1) = 0
   ID(2) = 0
   IDEF = 0
   ITWIN = 0
   ISTRNG = 0
   ICOOP = 0
   ITRY = 0
   IRDCHK = 0
   IRAND = 0
   IPARTY = 1
   IND = 0
   MY = 0
   INDEF = 5
   IOPP = 0
   PROB = .2
   K75R = 0
   RETURN

10 IF (IRAND .EQ. 1) GOTO 70
   IOPP = IOPP + J
   HIST(IND,J+1) = HIST(IND,J+1) + 1
   IF (M .EQ. 15 .OR. MOD(M,15) .NE. 0 .OR. IRAND .EQ. 2) GOTO 25
   IF (HIST(1,1) / (M - 2) .GE. .8) GOTO 25
   IF (IOPP * 4 .LT. M - 2 .OR. IOPP * 4 .GT. 3 * M - 6) GOTO 25
   DO 12 IA = 1,4
12 ROW(IA) = HIST(IA,1) + HIST(IA,2)

   DO 14 IB = 1,2
     SUM = .0
     DO 13 IA = 1,4
13   SUM = SUM + HIST(IA,IB)
14 COL(IB) = SUM

   SUM = .0
   DO 16 IA = 1,4
     DO 16 IB = 1,2
       EX = ROW(IA) * COL(IB) / (M - 2)
       IF (EX .LE. 1.) GOTO 16
       SUM = SUM + ((HIST(IA,IB) - EX) ** 2) / EX
16 CONTINUE

   IF (SUM .GT. 3) GOTO 25
   IRAND = 1
   K75R = 1
   RETURN

25 IF (ITRY .EQ. 1 .AND. J .EQ. 1) IBURN = 1
   IF (M .LE. 37 .AND. J .EQ. 0) ITWIN = ITWIN + 1
   IF (M .EQ. 38 .AND. J .EQ. 1) ITWIN = ITWIN + 1
   IF (M .GE. 39 .AND. ITWIN .EQ. 37 .AND. J .EQ. 1) ITWIN = 0
   IF (ITWIN .EQ. 37) GOTO 80
   IDEF = IDEF * J + J
   IF (IDEF .GE. 20) GOTO 90
   IPARTY = 3 - IPARTY
   ID(IPARTY) = ID(IPARTY) * J + J
   IF (ID(IPARTY) .GE. INDEF) GOTO 78
   IF (ICOOP .GE. 1) GOTO 80
   IF (M .LT. 37 .OR. IBURN .EQ. 1) GOTO 34
   IF (M .EQ. 37) GOTO 32
   IF (R .GT. PROB) GOTO 34
32 ITRY = 2
   ICOOP = 2
   PROB = PROB + .05
   GOTO 92

34 IF (J .EQ. 0) GOTO 80
   GOTO 90

70 IRDCHK = IRDCHK + J * 4 - 3
   IF (IRDCHK .GE. 11) GOTO 75
   K75R = 1
   RETURN

75 IRAND = 2
   ICOOP = 2
   K75R = 0
   RETURN

78 ID(IPARTY) = 0
   ISTRNG = ISTRNG + 1
   IF (ISTRNG .EQ. 8) INDEF = 3
80 K75R = 0
   ITRY = ITRY - 1
   ICOOP = ICOOP - 1
   GOTO 95

90 ID(IPARTY) = ID(IPARTY) + 1
92 K75R = 1
95 IND = 2 * MY + J + 1
   MY = K75R
   RETURN
   END

Burada GOTO ifadesinin çok ötesine geçen birçok sorun var; GOTO'nun ifadesinin biraz günah keçisi olduğunu düşünüyorum. Ancak kontrol akışı burada kesinlikle net değil ve kod, neler olup bittiğini çok net olmayan şekillerde bir araya getiriliyor. Yorum eklemeden veya daha iyi değişken isimleri kullanmadan bile, bunu GOTO'suz blok yapısına değiştirmek okumayı ve takip etmeyi çok kolaylaştıracak.


4
çok doğru :-) Söylemeye değer: eski FORTAN ve BASIC blok yapılara sahip değildi, böylece bir THEN cümlesi bir satırda tutamazsa GOTO tek alternatif oldu.
Christophe

Sayı yerine metin etiketleri veya numaralandırılmış satırlardaki en azından yorumlar çok yardımcı olacaktır.
Cees Timmerman

FORTRAN-IV günlerimde: GOTO'yu IF / ELSE IF / ELSE blokları, WHILE döngüleri ve BREAK ve NEXT döngülerini uygulamak için kullandım. Birisi bana spagetti kodunun kötülüğünü ve blok yapılarınızı GOTO ile uygulamak zorunda olsanız bile neden önlemek için bir yapı kurmanız gerektiğini gösterdi. Daha sonra ön işlemciyi kullanmaya başladım (RATFOR, IIRC). Goto özünde kötü değildir, sadece bir montajcı dalına yönelik talimatlarla eşleşen aşırı güçlü, düşük seviyeli bir yapıdır. Diliniz yetersiz olduğu için kullanmak zorundaysanız, uygun blok yapılarını oluşturmak veya güçlendirmek için kullanın.
nigel222

@CeesTimmerman: Bu bahçe çeşitliliği FORTRAN IV kodudur. FORTRAN IV'te metin etiketleri desteklenmiyordu. Dilin daha yeni sürümlerinin onları destekleyip desteklemediğini bilmiyorum. Kodla aynı satırdaki yorumlar, standart FORTRAN IV'te desteklenmedi, ancak satıcıya özel uzantılar olsa da bunları desteklemek için desteklenmedi. "Mevcut" FORTRAN standardının ne dediğini bilmiyorum: FORTRAN'ı uzun zaman önce terk ettim ve kaçırmıyorum. (En son FORTRAN kodu, 1970'lerin başlarında
PASCAL'a

1
@CeesTimmerman: Satıcıya özel uzantı. Genel olarak kod yorumlarda gerçekten utangaçtır. Ayrıca, daha sonra satır eklemeyi kolaylaştırmak için bazı yerlerde sık kullanılan, satır numaralarını yalnızca CONTINUE ve FORMAT ifadelerine koyarak yapılan bir sözleşme vardır. Bu kod bu kurallara uymuyor.
John R. Strohm,

0

Sürdürülebilir programlama ilkelerinden biri kapsüllemedir . Önemli olan, tanımlanmış bir arabirim kullanarak bir modül / rutin / alt yordam / bileşen / nesne ile arabirim oluşturduğunuz ve yalnızca bu arabirim ve sonuçlar tahmin edilebilir olacaktır (ünitenin etkin bir şekilde test edildiği varsayılarak).

Tek bir kod biriminde aynı prensip geçerlidir. Yapısal programlama veya nesne yönelimli programlama ilkelerini tutarlı bir şekilde uygularsanız, şunları yapamazsınız:

  1. kodda beklenmeyen yollar oluşturun
  2. tanımlanmamış veya izin verilmeyen değişken değerleri olan kod bölümlerine varmak
  3. tanımlanmamış veya izin verilmeyen değişken değerleriyle kodun yolundan çıkma
  4. bir işlem birimini tamamlamak başarısız
  5. kod veya veri bölümlerini etkin bir şekilde ölü olan, ancak çöp temizleme ve yeniden tahsisat için uygun olmayan bellekte bırakın;

Bu işleme hatalarının en yaygın belirtilerinden bazıları arasında bellek sızıntısı, bellek istifleme, işaretçi taşması, çökmeler, eksik veri kayıtları, kayıt ekleme / chg / silme istisnaları, bellek sayfası hataları vb.

Bu sorunların kullanıcı tarafından gözlemlenebilir bulguları arasında kullanıcı arabirimi kilitlenmesi, kademeli olarak performans düşürme, eksik veri kayıtları, işlemlerin başlatılamaması veya tamamlanamaması, bozuk veriler, ağ kesintileri, elektrik kesintileri, gömülü sistem arızaları (füzelerin kontrolünün kaybından) hava trafik kontrol sistemlerinde izleme ve kontrol kabiliyetinin kaybı), zamanlayıcı hataları vb. Katalog çok geniş.


3
Bir gotokere bile söylemeden cevap verdin . :)
Robert Harvey

0

Goto tehlikelidir, çünkü genellikle ihtiyaç duyulmadığında kullanılır. İhtiyacı olmayan bir şey kullanmak tehlikelidir, ama özellikle de git . Google’a giderseniz, goto’nun neden olduğu birçok hata göreceksiniz, bu onu kullanmamanız için bir neden değil (dil özelliklerini kullandığınızda hatalar her zaman olur, çünkü programlamada özündedir) için Goto kullanım.


Nedenleri kullanmayın / kullanma goto ifadesi :

  • Eğer bir döngü gerekiyorsa, kullanmak zorunda whileya for.

  • Koşullu atlama yapmanız gerekiyorsa, if/then/else

  • Prosedüre ihtiyacınız varsa, bir fonksiyon / yöntem çağırın.

  • Bir fonksiyondan vazgeçmeniz gerekirse, sadece return.

Doğru gotokullanıldığını ve kullanıldığını gördüğüm yerlere parmaklarıma güvenebilirim .

  • CPython
  • libKTX
  • muhtemelen birkaç tane daha

LibKTX’de aşağıdaki kodu içeren bir işlev vardır.

if(something)
    goto cleanup;

if(bla)
    goto cleanup;

cleanup:
    delete [] array;

Şimdi bu yerde gotoyararlı çünkü dil C:

  • bir fonksiyonun içindeyiz
  • Bir temizleme işlevi yazamıyoruz (çünkü başka bir kapsam giriyoruz ve erişilebilir arayan işlevi durumuna getirmek daha fazla yüklüyor)

Bu kullanım durumu faydalıdır çünkü C'de sınıflarımız yoktur, bu yüzden temizlemenin en basit yolu a kullanmaktır goto.

Eğer C ++ 'da aynı koda sahip olsaydık, artık goto'ya gerek kalmaz:

class MyClass{
    public:

    void Function(){
        if(something)
            return Cleanup(); // invalid syntax in C#, but valid in C++
        if(bla)
            return Cleanup(); // invalid syntax in C#, but valid in C++
    }

    // access same members, no need to pass state (compiler do it for us).
    void Cleanup(){

    }



}

Ne tür böceklere yol açabilir? Herhangi bir şey. Sonsuz döngüler, yanlış uygulama sırası, istifleme vidası ..

Belgeli bir durum , SSL’deki Man’a Goto’nun yanlış kullanımından kaynaklanan orta saldırılarda izin veren bir güvenlik açığıdır: İşte makale

Bu bir yazım hatası, ancak bir süredir fark edilmedi, kod başka bir şekilde yapılandırılmışsa, doğru bir şekilde test edildiğinde böyle bir hata mümkün olamazdı.


2
"Goto" kullanımının SSL hatalarından tamamen yararsız olduğunu açık bir şekilde açıklayan çok sayıda yorum var - hata, bir satır kodun dikkatsiz bir şekilde çoğaltılmasından kaynaklandı, bu nedenle bir kez şartlı ve bir kez koşulsuz olarak yapıldı.
gnasher729

Evet, kabul etmeden önce daha iyi bir tarih böceği hatası örneği bekliyorum. Söylendiği gibi; Bu kod satırında ne olduğu gerçekten önemli değil; Kıvrımlı ayraçların eksikliği onu uygulamış ve ne olursa olsun bir hataya neden olmuş olacaktır. Yine de merak ediyorum; "Yığın Vida" nedir?
Akiva,

1
Daha önce PL / 1 CICS'de çalıştığım koddan bir örnek. Program, tek hat haritalarından oluşan bir ekran ortaya koydu. Ekran döndüğünde, gönderdiği haritaların dizisini buldu. Bunun elemanlarını dizini bir dizide bulmak için kullandık ve daha sonra bu dizini değişkenlerin bir dizinine GOTO yapmak için kullandı, böylece o bireysel haritayı işleyebildi. Gönderilen haritalar dizisi hatalıysa (veya bozulmuş olsaydı), o zaman yanlış etikete GOTO yapmayı ya da etiket değişkenleri dizisinin bitiminden sonra bir elemana eriştiğinden daha kötü bir çöküş deneyebilirdi. Vaka tipi sözdizimini kullanmak için yeniden yazıldı.
Kickstart
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.