Boş sonlandırılmış dize - Null-terminated string

Olarak bilgisayar programlama , bir boş-sonlu dizisi a, karakter dizisi bir şekilde saklanan bir dizi karakter içeren ve bir ile sona boş karakter (bu yazıda NULL adı sıfır değerine sahip bir karakter,). Alternatif isimler C dize belirtir, C programlama dili ve ASCIIZ (C ASCII dışında kodlamalar kullanabilirsiniz rağmen).

Bir dizgenin uzunluğu (ilk) NUL aranarak bulunur. Bu , dize uzunluğuna göre O( n ) ( doğrusal zaman ) aldığından yavaş olabilir . Bu aynı zamanda bir dizenin NUL içeremeyeceği anlamına gelir (bellekte bir NUL vardır, ancak dizenin "içinde" değil, son karakterden sonra gelir).

Tarih

Boş sonlandırılmış dizeler tarafından üretildi .ASCIZdirektifi PDP-11 montaj dilleri ve ASCIZdirektifi MAKRO-10 için makro montaj dili PDP-10 . Bunlar, C programlama dilinin geliştirilmesinden önce gelir, ancak diğer dize biçimleri sıklıkla kullanılırdı.

C (ve türetildiği diller) geliştirildiğinde, bellek son derece sınırlıydı, bu nedenle bir dizenin uzunluğunu depolamak için yalnızca bir bayt ek yük kullanmak çekiciydi. O zamanlar genellikle "Pascal dizesi" (daha modern bir terim " uzunluk ön eki " olarak adlandırılır) olarak adlandırılan tek popüler alternatif, dizenin uzunluğunu depolamak için önde gelen bir bayt kullanırdı. Bu, dizenin NUL içermesine ve önceden depolanmış bir dizenin uzunluğunu bulmasına izin verir, yalnızca bir bellek erişimine ihtiyaç duyar (O(1) (sabit) zaman ), ancak dize uzunluğu 255 karakterle sınırlıdır (8 bit bayt kullanan bir makinede) ). C tasarımcısı Dennis Ritchie , bir dizgenin uzunluğundaki sınırlamadan kaçınmak için boş sonlandırma kuralına uymayı seçti ve çünkü kendi deneyimine göre sayımı sürdürmek, bir sonlandırıcı kullanmaktan daha az uygun görünüyordu.

Bunun CPU komut seti tasarımı üzerinde bir etkisi oldu . 1970'lerde ve 1980'lerde, Zilog Z80 ve DEC VAX gibi bazı CPU'lar, uzunluk önekli dizeleri işlemek için özel talimatlara sahipti. Bununla birlikte, boş sonlandırılmış dize çekiş kazandıkça, CPU tasarımcıları, örneğin IBM'in 1992'de ES/9000 520'ye "Mantıksal Dizi Yardımı" talimatlarını ekleme kararında ve vektör dizisi talimatlarında görüldüğü gibi, bunu dikkate almaya başladılar . 2015 yılında IBM z13 .

ACM Queue'da yazan FreeBSD geliştiricisi Poul-Henning Kamp , 2 baytlık (bir baytlık değil) uzunluktaki boş sonlandırılmış dizelerin zaferini "şimdiye kadarki en pahalı bir baytlık hata" olarak nitelendirdi.

sınırlamalar

Uygulaması basit olmakla birlikte, bu gösterim hatalara ve performans sorunlarına eğilimlidir.

Boş sonlandırma, tarihsel olarak güvenlik sorunları yaratmıştır . Bir dizenin ortasına eklenen bir NUL, onu beklenmedik bir şekilde kesecektir. Yaygın bir hata, NUL için ek alan ayırmamaktı, bu nedenle bitişik bellek üzerine yazılmıştır. Bir diğeri, bellek bloğu zaten sıfır içerdiğinden test sırasında genellikle algılanmayan NUL'u hiç yazmamaktı. Uzunluğu bulma masrafı nedeniyle, birçok program bir dizeyi sabit boyutlu bir arabelleğe kopyalamadan önce zahmet etmedi ve çok uzunsa arabellek taşmasına neden oldu.

Sıfır depolayamama, metin ve ikili verilerin farklı tutulmasını ve farklı işlevler tarafından ele alınmasını gerektirir (ikincisi, sağlanacak verilerin uzunluğunu da gerektirir). Bu, yanlış işlev kullanıldığında kod fazlalığına ve hatalara yol açabilir.

Uzunluğu bulma ile ilgili hız sorunları, genellikle, onu yine de O( n ) olan başka bir işlemle , örneğin in 'de birleştirerek hafifletilebilir strlcpy. Ancak bu her zaman sezgisel bir API ile sonuçlanmaz .

Karakter kodlamaları

Boş sonlandırılmış dizeler, kodlamanın hiçbir yerde sıfır bayt (0x00) kullanmamasını gerektirir, bu nedenle olası her ASCII veya UTF-8 dizesini saklamak mümkün değildir . Ancak, ASCII veya UTF-8'in alt kümesini (NUL hariç her karakter) boş sonlandırılmış dizelerde depolamak yaygındır. Bazı sistemler , NUL'u sıfır olmayan iki bayt (0xC0, 0x80) olarak kodlayan ve böylece olası tüm dizelerin saklanmasına izin veren " değiştirilmiş UTF-8 " kullanır . Buna UTF-8 standardı tarafından izin verilmez, çünkü aşırı uzun bir kodlamadır ve bir güvenlik riski olarak görülür. Bunun yerine, UTF-8'de kullanılmayan 0xFE veya 0xFF gibi başka bir bayt dizenin sonu olarak kullanılabilir.

UTF-16 , 2 baytlık tamsayılar kullanır ve her iki bayt da sıfır olabileceğinden (aslında , ASCII metnini temsil ederken diğer her bayttır), boş sonlandırılmış bir bayt dizesinde saklanamaz. Ancak bazı diller, 16 bitlik bir NUL ile sonlandırılan 16 bitlik UTF-16 karakterlerinden oluşan bir dize uygular.

İyileştirmeler

C string işlemeyi daha az hataya açık hale getirmek için birçok girişimde bulunuldu. Bir strateji gibi daha güvenli işlevleri eklemektir strdupve strlcpyiken, güvensiz fonksiyonlarının kullanımını kaldırıyoruz gibi gets. Diğeri, yalnızca güvenli aramaların yapılabilmesi için C dizelerinin etrafına nesne yönelimli bir sarmalayıcı eklemektir. Ancak yine de güvenli olmayan işlevleri çağırmak mümkündür.

Çoğu modern kitaplık, C dizelerini 32 bit veya daha büyük uzunluk değeri içeren bir yapıyla değiştirir (ön ekli uzunluklar için şimdiye kadar düşünülenden çok daha fazla) ve dönüştürmeyi hızlandırmak için genellikle başka bir işaretçi, bir referans sayısı ve hatta bir NUL ekler. bir C dizesine geri dönün. Bellek artık çok daha büyük, öyle ki, her dizeye 3 (veya 16 veya daha fazla) bayt eklenmesi gerçek bir sorunsa, yazılım o kadar çok küçük dizeyle uğraşmak zorunda kalacak ki, başka bir depolama yöntemi daha fazla bellek tasarrufu sağlayacaktır. (örneğin, bir karma tablosunun daha az bellek kullanacağı kadar çok kopya olabilir ). Örnekler arasında C ++ Standart Template Library std::string , QT QString , MFC CString ve C tabanlı uygulama CFStringdan Çekirdek Vakfı yanı sıra Objective-C kardeş NSStringdan Vakfı Apple tarafından hem. Halat gibi ipleri saklamak için daha karmaşık yapılar da kullanılabilir .

Ayrıca bakınız

Referanslar