"Güvenli tip" ne demektir?
"Güvenli tip" ne demektir?
Yanıtlar:
Tür güvenliği, derleyicinin derleme sırasında türleri doğrulayacağı ve bir değişkene yanlış tür atamaya çalıştığınızda bir hata atacağı anlamına gelir.
Bazı basit örnekler:
// Fails, Trying to put an integer in a string
String one = 1;
// Also fails.
int foo = "bar";
Bu, yöntem bağımsız değişkenleri için de geçerlidir, çünkü bunlara açık türleri geçiriyorsunuz:
int AddTwoNumbers(int a, int b)
{
return a + b;
}
Bunu kullanarak aramayı denediysem:
int Sum = AddTwoNumbers(5, "5");
Bir dize ("5") geçiriyorum ve bir tamsayı bekliyor çünkü derleyici bir hata atmak.
Javascript gibi gevşek yazılan bir dilde şunları yapabilirim:
function AddTwoNumbers(a, b)
{
return a + b;
}
Eğer böyle çağırırsam:
Sum = AddTwoNumbers(5, "5");
Javascript otomatik olarak 5'i bir dizeye dönüştürür ve "55" değerini döndürür. Bunun nedeni, dize birleştirmesi için + işaretini kullanan javascripttir. Tip farkında olmak için aşağıdaki gibi bir şey yapmanız gerekir:
function AddTwoNumbers(a, b)
{
return Number(a) + Number(b);
}
Veya, muhtemelen:
function AddOnlyTwoNumbers(a, b)
{
if (isNaN(a) || isNaN(b))
return false;
return Number(a) + Number(b);
}
Eğer böyle çağırırsam:
Sum = AddTwoNumbers(5, " dogs");
Javascript otomatik olarak 5'i bir dizeye dönüştürür ve "5 köpek" döndürmek için ekler.
Tüm dinamik diller javascript kadar affedici değildir (Aslında dinamik bir dil, gevşek bir yazılan dil anlamına gelmez (bkz. Python)), bazıları aslında geçersiz tür dökümde bir çalışma zamanı hatası verecektir.
Uygun olsa da, kolayca gözden kaçabilen ve sadece çalışan programı test ederek tanımlanabilen birçok hataya kadar açar. Şahsen, derleyicimin bu hatayı yapıp yapmadığımı söylemesini tercih ederim.
Şimdi C # 'a dönelim ...
C #, kovaryans adı verilen bir dil özelliğini destekler , bu temel olarak bir alt tür için bir taban türünü değiştirebileceğiniz ve hataya neden olamayacağınız anlamına gelir, örneğin:
public class Foo : Bar
{
}
Burada, Bar alt sınıflarını oluşturan yeni bir sınıf (Foo) oluşturdum. Şimdi bir yöntem oluşturabilirim:
void DoSomething(Bar myBar)
Ve argüman olarak bir Foo veya bir Bar kullanarak her ikisi de hataya neden olmadan çalışacaktır. Bu çalışır çünkü C #, herhangi bir Bar alt sınıfının Bar arabirimini uygulayacağını bilir.
Ancak, tersini yapamazsınız:
void DoSomething(Foo myFoo)
Bu durumda, Bar'ı bu yönteme geçiremiyorum, çünkü derleyici Bar'ın Foo'nun arayüzünü uyguladığını bilmiyor. Bunun nedeni, bir alt sınıfın üst sınıftan çok farklı olabilmesidir (ve genellikle olacaktır).
Tabii ki, şimdi derin sorunun dışına çıktım ve orijinal sorunun kapsamı dışına çıktım, ama bilmek için iyi şeyler :)
Tip güvenliği statik / dinamik yazım veya güçlü / zayıf yazım ile karıştırılmamalıdır.
Güvenli bir dil, verilerin üzerinde gerçekleştirilebilecek tek işlemin, veri türü tarafından gözüken dil olduğu dildir. Yani, verileriniz türdeyse X
ve X
işlemi desteklemiyorsa y
, dil yürütmenize izin vermez y(X)
.
Bu tanım ilgili kurallar ayarlayabilirsiniz vermez zaman bu kontrol edilir. Genellikle istisnalar dışında derleme zamanında (statik yazma) veya çalışma zamanında (dinamik yazma) olabilir. Bazı statik olarak yazılan diller bir türden diğerine döküm verilerine sizi izin verir ve atmalarını geçerliliği zamanında (bir yayın yapmaya çalışıyor hayal kontrol edilmelidir: Hem biraz olabilir Object
a Consumer
derleyici hayır var - kabul edilebilir olup olmadığını bilmenin yolu).
Tip güvenliği mutlaka güçlü bir şekilde yazılmış olmak anlamına gelmez - bazı diller kötü bir şekilde zayıf bir şekilde yazılmıştır, ancak yine de tartışmalı olarak güvenli bir şekilde yazılmıştır. Örneğin Javascript'i ele alalım: onun tip sistemi geldikleri kadar zayıf, ama yine de kesin olarak tanımlanmış. Verilerin otomatik olarak yayınlanmasına izin verir (örneğin, dizelere ints), ancak iyi tanımlanmış kurallar dahilinde. Bildiğim kadarıyla bir Javascript programının tanımsız bir şekilde davranacağı hiçbir durum yoktur ve yeterince zekiyseniz (ben değilim), Javascript kodunu okurken ne olacağını tahmin edebilmelisiniz.
Güvenli olmayan bir programlama diline örnek olarak C: dizinin sınırları dışında bir dizi değerini okumak / yazmak , belirtime göre tanımlanmamış bir davranışa sahiptir . Ne olacağını tahmin etmek imkansız. C, bir tür sistemi olan, ancak tür güvenli olmayan bir dildir.
Tür güvenliği sadece derleme zamanı kısıtlaması değil, çalışma zamanı kısıtlamasıdır. Bunca zamandan sonra bile, buna daha fazla netlik ekleyebiliriz.
Tip güvenliği ile ilgili 2 ana konu vardır. Bellek ** ve veri tipi (ilgili işlemlerle).
A char
genellikle karakter başına 1 bayt veya 8 bit gerektirir (dile bağlıdır, Java ve C # 16 bit gerektiren unicode karakterleri depolar). A int
, 4 bayt veya 32 bit (genellikle) gerektirir.
Görme:
char: |-|-|-|-|-|-|-|-|
int : |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-|
Güvenli bir dil, bir int'in çalışma zamanında karaktere eklenmesine izin vermez (bu, bir tür sınıf dökümünü veya bellek istisnasını atmalıdır). Ancak, güvenli olmayan bir dilde, 3 bitişik daha fazla bayt bellekte mevcut verilerin üzerine yazarsınız.
int >> char:
|-|-|-|-|-|-|-|-| |?|?|?|?|?|?|?|?| |?|?|?|?|?|?|?|?| |?|?|?|?|?|?|?|?|
Yukarıdaki durumda, sağdaki 3 baytın üzerine yazılır, bu nedenle bu belleğe tahmin edilebilir bir char değeri almayı bekleyen herhangi bir işaretçi (mesela 3 ardışık karakter) artık çöp olacaktır. Bu undefined
, programınızda (veya işletim sisteminin belleği nasıl ayırdığına bağlı olarak diğer programlarda daha da kötüleşmesine neden olur - bu günlerde pek olası değildir).
** Bu ilk sorun teknik olarak veri türü ile ilgili olmasa da, güvenli diller yazarak doğası gereği bu sorunu giderir ve bellek tahsisinin "nasıl göründüğünden" habersiz olanlar için sorunu görsel olarak açıklar.
Daha ince ve doğrudan tip sorunu, iki veri tipinin aynı bellek tahsisini kullanmasıdır. İmzasız bir int vs int alın. Her ikisi de 32 bittir. (Kolayca bir char [4] ve int olabilir, ancak daha yaygın olan konu uint vs. int'tir).
|-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-|
|-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-|
Güvenli olmayan bir dil, programcının 32 bitlik düzgün bir şekilde ayrılmış bir yayılma alanına başvurmasına izin verir, ancak işaretsiz bir int değeri bir int boşluğuna okunduğunda (veya tersi), yine undefined
davranışlarımız olur. Bunun bir bankacılık programında neden olabileceği sorunları düşünün:
"Dostum! 30 dolardan fazla abarttım ve şimdi 65.506 dolar kaldım !!"
... 'dersinde, bankacılık programları çok daha büyük veri türleri kullanıyor. ;) LOL!
Diğerlerinin de belirttiği gibi, bir sonraki konu tipler üzerinde hesaplama işlemleri. Bu zaten yeterince kapsanmıştır.
Bugün çoğu programcı, C veya C ++ gibi bir şey kullanmadıkça bu tür şeyler için endişelenmenize gerek yoktur. Bu dillerin her ikisi de, derleyicilerin riski en aza indirmek için gösterdiği çabalara rağmen, programcıların çalışma zamanında tür güvenliğini (doğrudan bellek referansı) kolayca ihlal etmelerine olanak tanır. ANCAK, bunların hepsi kötü değil.
Bu dillerin bu kadar hızlı hesaplanmasının bir nedeni de, örneğin Java gibi çalışma zamanı işlemleri sırasında tür uyumluluğunu doğrulayarak yüklenmemeleri. Geliştiricinin, birlikte bir dize ve int eklemeyecek iyi bir rasyonel varlık olduğunu varsayarlar ve bunun için geliştirici hız / verimlilik ile ödüllendirilir.
Buradaki birçok cevap, tip güvenliğini statik yazma ve dinamik yazma ile birleştiriyor. Dinamik olarak yazılan bir dil (küçük konuşma gibi) de tür için güvenli olabilir.
Kısa bir cevap: herhangi bir işlem tanımlanmamış davranışa yol açmazsa, dilin güvenli olduğu kabul edilir. Birçoğu, bir dilin kesinlikle yazılması için gereken açık tip dönüşüm gereksinimini dikkate alır , çünkü otomatik dönüşümler bazen iyi tanımlanmış ancak beklenmedik / sezgisel olmayan davranışlara yol açabilir.
if no operation leads to undefined behavior
.
Bilgisayar bilimleri dalından değil, liberal sanat dalından bir açıklama:
İnsanlar bir dil veya dil özelliğinin tür güvenli olduğunu söylediklerinde, dilin örneğin tamsayı olmayan bir şeyi tamsayı bekleyen bir mantığa geçirmenizi önlemeye yardımcı olacağı anlamına gelir.
Örneğin, C # 'ta bir işlevi şöyle tanımlarım:
void foo(int arg)
Derleyici bunu yapmama engel olacak:
// call foo
foo("hello world")
Diğer dillerde, derleyici beni durdurmaz (veya derleyici yoktur ...), bu nedenle dize mantığa geçirilir ve muhtemelen kötü bir şey olur.
Güvenli diller yazın "derleme zamanında" daha fazla yakalamaya çalışın.
Aşağı tarafta, güvenli diller yazarken, "123" gibi bir dizeniz olduğunda ve bunun üzerinde int gibi çalışmak istediğinizde, dizeyi int'e dönüştürmek için daha fazla kod yazmanız veya bir int 123 gibi ve "Cevap 123" gibi bir mesajda kullanmak istiyorum, onu bir dizeye dönüştürmek / yayınlamak için daha fazla kod yazmak zorunda.
Daha iyi bir anlayış elde etmek için, kodu güvenli dil (C #) ve NOT güvenli dil (javascript) olarak gösteren aşağıdaki videoyu izleyin.
http://www.youtube.com/watch?v=Rlw_njQhkxw
Şimdi uzun metin için.
Tip güvenliği, tip hatalarının önlenmesi anlamına gelir. Tür hatası, bir türün veri türü BİLİNMEYEN başka bir türe atandığında ve istenmeyen sonuçlar aldığımızda oluşur.
Örneğin JavaScript, tür güvenli bir dil DEĞİLDİR. Aşağıdaki kodda “num” sayısal bir değişkendir ve “str” dizedir. Javascript "num + str" yapmamı sağlıyor, şimdi GUESS aritmetik veya birleştirme yapacak.
Şimdi aşağıdaki kod için sonuçlar “55” dir ancak önemli olan, ne tür bir işlem yapacağına dair kafa karışıklığıdır.
Javascript bir tür güvenli dil olmadığı için bu oluyor. Kısıtlama olmaksızın bir veri türünü diğer türe ayarlamaya izin verir.
<script>
var num = 5; // numeric
var str = "5"; // string
var z = num + str; // arthimetic or concat ????
alert(z); // displays “55”
</script>
C # bir tür güvenli dildir. Bir veri türünün diğer veri türüne atanmasına izin vermez. Aşağıdaki kod, farklı veri türlerinde "+" operatörüne izin vermez.
Type-safe, bir değişken, dönüş değeri veya bağımsız değişken için veri türünün programlı olarak belirli ölçütlere uyması gerektiği anlamına gelir.
Pratikte bu, 7 (bir tamsayı tipi) "7" den farklıdır (dize türünün tırnak içine alınmış bir karakteri).
PHP, Javascript ve diğer dinamik kodlama dilleri genellikle zayıf yazılmıştır, çünkü bazen "7" + 3 eklemeye çalışırsanız (7) + 3 eklemeye çalışırsanız (7) + 'yı (tamsayı) 7'ye dönüştürürler. açıkça (ve Javascript, birleştirme için "+" karakterini kullanır).
C / C ++ / Java bunu anlamayacak veya sonucu "73" ile birleştirecektir. Tür güvenliği, tür gereksinimini açık yaparak koddaki bu tür hataları önler.
Tip güvenliği çok faydalıdır. Yukarıdaki "7" + 3'ün çözümü döküm (int) "7" + 3 (10'a eşit) tipinde olacaktır.
Konsept:
Anlamlar gibi çok basit Tip Güvenli olmak için, değişkenin türünün güvenli olması gerektiği gibi olmasını sağlar
yani her şey depolama alanınızın değişkenleri açısından güvenliği ile ilgilidir.
Şu açıklamayı deneyin ...
TypeSafe, değişkenlerin derleme zamanında uygun atama için statik olarak denetlendiği anlamına gelir. Örneğin, bir dizgiye veya bir tamsayıya bakın. Bu iki farklı veri türü çapraz olarak atanamaz (yani, bir dizeye tamsayı atayamazsınız veya tamsayıya dize atayamazsınız).
Normal olmayan davranışlar için şunları göz önünde bulundurun:
object x = 89;
int y;
bunu yapmaya çalışırsanız:
y = x;
derleyici, System.Object öğesini bir Tamsayıya dönüştüremediğini bildiren bir hata atar. Bunu açıkça yapmanız gerekir. Bunun bir yolu:
y = Convert.ToInt32( x );
Yukarıdaki atama güvenli değildir. Tipik güvenli atama, türlerin doğrudan birbirine atanabileceği alandır.
ASP.NET'te tür olmayan güvenli olmayan koleksiyonlar (ör. Uygulama, oturum ve görünüm durumu koleksiyonları) bulunmaktadır. Bu koleksiyonlarla ilgili iyi haber şu ki (birden çok sunucu durumu yönetimi konusundaki düşünceleri en aza indirerek) üç koleksiyonun herhangi birine hemen hemen tüm veri türlerini koyabilirsiniz. Kötü haber: Bu koleksiyonlar güvenilir olmadığından, değerleri geri aldığınızda değerleri uygun şekilde yayınlamanız gerekir.
Örneğin:
Session[ "x" ] = 34;
iyi çalışıyor. Ancak tamsayı değerini geri atamak için şunları yapmanız gerekir:
int i = Convert.ToInt32( Session[ "x" ] );
Tesisin tipik güvenli koleksiyonları kolayca uygulamanıza yardımcı olacak yollar için jenerikler hakkında bilgi edinin.
C # tipik bir dildir ancak C # 4.0 ile ilgili makaleleri izleyin; ilginç dinamik olasılıklar tezgâh (C # 'nin Seçenek Katı: Kapalı ... göreceğimiz iyi bir şey mi?)
Tür-Güvenli, yalnızca erişim yetkisi verilen bellek konumlarına ve yalnızca iyi tanımlanmış, izin verilebilir yollara erişen koddur. Güvenli kod, söz konusu nesne için geçersiz bir nesne üzerinde işlem gerçekleştiremiyor. C # ve VB.NET dil derleyicileri her zaman JIT derlemesi sırasında tür güvenli olduğu doğrulanan tip-güvenli kod üretir.
Güvenli tip, bir program değişkenine atanabilecek değer kümesinin iyi tanımlanmış ve test edilebilir ölçütlere uyması gerektiği anlamına gelir. Tür açısından güvenli değişkenler, daha sağlam programlara yol açar, çünkü değişkenleri işleyen algoritmalar, değişkenin yalnızca iyi tanımlanmış bir değer kümesinden birini alacağına güvenebilir. Bu güveni korumak, verilerin ve programın bütünlüğünü ve kalitesini garanti eder.
Birçok değişken için, bir değişkene atanabilecek değerler kümesi programın yazıldığı sırada tanımlanır. Örneğin, "renk" adlı bir değişkenin "kırmızı", "yeşil" veya "mavi" değerlerini almasına izin verilebilir ve asla başka bir değer almaz. Diğer değişkenler için bu kriterler çalışma zamanında değişebilir. Örneğin, "renk" adı verilen bir değişkenin, yalnızca "kırmızı", "yeşil" ve "mavi" ifadelerinin üç değer olduğu ilişkisel bir veritabanındaki "Renkler" tablosunun "ad" sütunundaki değerleri almasına izin verilebilir. "Renkler" tablosundaki "ad" için, ancak bilgisayar programının başka bir kısmı program çalışırken bu listeye ekleyebilir ve değişken, Renkler tablosuna eklendikten sonra yeni değerleri alabilir .
Birçok tip-güvenli dil, değişkenler için kesin tiplerin tanımlanmasında ısrar ederek ve sadece bir değişkene aynı "tip" değerlerinin atanmasına izin vererek "tip-emniyet" yanılsamasını verir. Bu yaklaşımla ilgili birkaç sorun var. Örneğin, bir program, bir kişinin doğduğu yıl olan bir "yearOfBirth" değişkenine sahip olabilir ve kısa bir tamsayı olarak yazmak için cazip gelebilir. Ancak, kısa bir tam sayı değildir. Bu yıl, 2009'dan küçük ve -10000'den büyük bir sayı. Bununla birlikte, program çalışırken bu set her yıl 1 büyür. Bunu "kısa int" yapmak yeterli değildir. Bu değişken türünü güvenli hale getirmek için gerekli olan, sayının her zaman -10000'den büyük ve bir sonraki takvim yılından daha az olmasını sağlayan bir çalışma zamanı doğrulama işlevidir.
Perl, Python, Ruby, SQLite ve Lua gibi dinamik yazmayı (veya ördek yazmayı veya manifest yazmayı) kullanan diller, yazılan değişkenler kavramına sahip değildir. Bu, programcıyı doğru olduğundan emin olmak için her değişken için bir çalışma zamanı doğrulama yordamı yazmaya zorlar veya açıklanamayan çalışma zamanı özel durumlarının sonuçlarına katlanır. Deneyimlerime göre, C, C ++, Java ve C # gibi statik olarak yazılan dillerde programcılar, statik olarak tanımlanmış türlerin tür güvenliğinden yararlanmak için tek yapmaları gereken şey olduğunu düşünmek için sık sık dururlar. Bu, birçok yararlı bilgisayar programı için doğru değildir ve herhangi bir bilgisayar programı için doğru olup olmadığını tahmin etmek zordur.
Uzun ve kısa .... Tip güvenliği ister misiniz? Öyleyse, bir değişkene bir değer atandığında, iyi tanımlanmış ölçütlere uyduğundan emin olmak için çalışma zamanı işlevleri yazın. Aşağı tarafı, her bilgisayar değişkeni için ölçütleri açıkça tanımlamanız gerektiğinden, çoğu bilgisayar programı için etki alanı analizini gerçekten zorlaştırmasıdır.