Bir diziye sınırların dışında erişmek ne kadar tehlikeli?


221

Bir diziye sınırlarının dışında ne kadar tehlikeli (C cinsinden)? Bazen dizinin dışından okudum (şimdi anlıyorum sonra programımın bazı bölümleri tarafından veya hatta bunun ötesinde kullanılan belleğe erişiyorum) ya da dizinin dışındaki bir dizine bir değer ayarlamaya çalışıyorum. Program bazen çöküyor, ancak bazen sadece beklenmedik sonuçlar vererek çalışıyor.

Şimdi bilmek istediğim, bu gerçekten ne kadar tehlikeli? Programıma zarar verirse, o kadar da kötü değil. Öte yandan, programımın dışındaki bir şeyi kırarsa, bir şekilde tamamen ilgisiz bir belleğe erişmeyi başardım, o zaman çok kötü, sanırım. Çok fazla 'her şey olabilir' okudum, 'segmentasyon en az kötü sorun olabilir' , 'sabit diskiniz pembeye dönüşebilir ve tek boynuzlu atlar pencerenizin altında şarkı söylüyor olabilir', hepsi güzel, ama gerçekte tehlike nedir?

Sorularım:

  1. Dizinin dışından değerleri okumak programım dışında herhangi bir şeye zarar verebilir mi? Sadece şeylere bakmanın hiçbir şeyi değiştirmediğini düşünürdüm, yoksa örneğin ulaştığım bir dosyanın 'son açılma' özelliğini değiştirir mi?
  2. Değerlerin dizi dışına çıkış yolu programım dışında herhangi bir şeye zarar verebilir mi? Bu Yığın Taşması sorusundan , herhangi bir bellek konumuna erişmenin mümkün olduğunu, herhangi bir güvenlik garantisi olmadığını topladım.
  3. Şimdi küçük programlarımı XCode içinden çalıştırıyorum. Bu, programımın kendi belleğinin dışına erişemediği bazı ekstra koruma sağlıyor mu? XCode'a zarar verebilir mi?
  4. Doğal olarak buggy kodumu güvenli bir şekilde çalıştırmak için herhangi bir öneriniz var mı?

OSX 10.7, Xcode 4.6 kullanıyorum.


Genel olarak, işletim sistemi kendini ve diğer süreçleri kötü niyetinizden koruyacaktır. Yine de, bu, büyük ölçüde güvenmek istediğiniz bir şey değildir.
Hot Licks

7
Ayrıca, hiçbir zaman sabit diskinizdeki bir dosyaya erişmeye ve dizinin sınırlarının dışına (koçunuzda) "ulaşmayacaksınız".
DrummerB

1
C dizisi hakkında sorduğunuza inanıyorum, değil mi? bu yüzden ObjC ile hiçbir ilgisi yoktur ve gerçekten herhangi bir IDE ile ilgili değildir.
Bryan Chen

17
İşte garip sonuçların en sevdiğim örneği (yığınla ilgileniyor, ama gerçekten aydınlatıcı buldum ...).
phipsgabler

Yanıtlar:


125

ISO C standardı (dilin resmi tanımı) söz konusu olduğunda, sınırlarının dışındaki bir diziye erişmenin " tanımlanmamış davranışı " vardır. Bunun gerçek anlamı:

taşınabilir olmayan veya hatalı bir program yapısının veya bu Uluslararası Standardın hiçbir şart getirmediği hatalı verilerin kullanılması üzerine davranış

Normatif olmayan bir not bu konuda genişler:

Olası tanımlanamayan davranışlar durumu öngörülemeyen sonuçlarla tamamen görmezden gelmekten, çeviri veya program yürütme sırasında ortamın karakteristiği olan (tanı mesajı verilmiş veya verilmeden) belgelenmiş bir şekilde davranmaya, bir çeviri veya yürütmeyi sonlandırmaya (düzenleme ile) kadar uzanır. bir teşhis mesajı).

İşte bu teori. Gerçek nedir?

"En iyi" durumda, ya (yaramazlık programınızı neden olabilir) Şu anda yayınlanmakta olan programın tarafından sahibi belleğin bazı parça erişirsiniz veya bu oluyor değil (ki muhtemelen programınıza neden sizin şu anda çalışan program tarafından sahip olunan segmentasyon hatası gibi bir şeyle kilitlenme). Veya programınızın sahip olduğu belleğe yazmaya çalışabilirsiniz, ancak bu salt okunur olarak işaretlenmiştir; bu muhtemelen programınızın çökmesine neden olacaktır.

Programınızın, eşzamanlı olarak çalışan işlemleri birbirinden korumaya çalışan bir işletim sistemi altında çalıştığı varsayılmaktadır. Kodunuz "çıplak metal" üzerinde çalışıyorsa, bir işletim sistemi çekirdeğinin veya gömülü bir sistemin parçası olup olmadığını söyleyin, o zaman böyle bir koruma yoktur; bu korumayı sağlaması gereken yanlış davranış kodunuzdur. Bu durumda, bazı durumlarda donanıma (veya yakındaki şeylere veya kişilere) fiziksel hasar da dahil olmak üzere hasar olasılığı oldukça yüksektir.

Korunan bir işletim sistemi ortamında bile korumalar her zaman% 100 değildir. Örneğin, ayrıcalıksız programların kök (yönetimsel) erişim elde etmesine izin veren işletim sistemi hataları vardır. Sıradan kullanıcı ayrıcalıklarında bile, hatalı çalışan bir program aşırı kaynakları (CPU, bellek, disk) tüketebilir ve muhtemelen tüm sistemi düşürebilir. Birçok kötü amaçlı yazılım (virüs vb.), Sisteme yetkisiz erişim sağlamak için arabellek taşmalarını kullanır.

(Tarihsel bir örnek: Çekirdek belleğe sahip bazı eski sistemlerde, sıkı bir döngüde tek bir bellek konumuna art arda erişmenin kelimenin tam anlamıyla bellek yığınının erimesine neden olabileceğini duydum . Diğer olasılıklar arasında bir CRT ekranın yok edilmesi ve okunmanın taşınması yer alıyor / sürücü kabininin harmonik frekansına sahip bir disk sürücüsünün kafasını bir masanın üzerinden geçip yere düşmesine neden olur.)

Ve her zaman endişelenecek Skynet var.

Sonuç olarak: kasıtlı olarak kötü bir şey yapmak için bir program yazabiliyorsanız , en azından teorik olarak, bir hatalı programın aynı şeyi yanlışlıkla yapabilmesi mümkündür .

Uygulamada, bu kadar çok MacOS X sistem üzerinde çalışan arabası programın çökmesi daha ciddi bir şey yapmak için gidiyor düşüktür. Ancak, buggy kodunun gerçekten kötü şeyler yapmasını tamamen önlemek mümkün değildir .


1
teşekkürler, aslında bunu tamamen anlıyorum. Ancak hemen bir takip sorusunu tetikler: bir başlangıç ​​programcısı, bilgisayarını kendi korkunç yaratımlarından korumak için ne yapabilir? Bir programı kapsamlı bir şekilde test ettikten sonra, dünyada serbest bırakabilirim. Ancak ilk deneme çalıştırması yanlış bir program olmak zorundadır. Sistemlerinizi kendinizden nasıl güvende tutuyorsunuz?
ChrisD

6
@ChrisD: Şanslı olma eğilimindeyiz. 8-)} Cidden, işletim sistemi düzeyinde koruma bugünlerde oldukça iyi. En kötüsü, kazara bir çatal bombası yazarsam, iyileşmek için yeniden başlatmam gerekebilir. Ancak, programınız tehlikeli olmanın kenarında bir şey yapmaya çalışmadığı sürece, sisteme gerçek hasar muhtemelen endişelenmeye değmez. Gerçekten endişeleniyorsanız, programı sanal bir makinede çalıştırmak kötü bir fikir olmayabilir.
Keith Thompson

1
Öte yandan, kullandığım bilgisayarlarda çok sayıda garip şey gördüm (bozuk dosyalar, kurtarılamayan sistem hataları, vb.) korkunç tanımsız davranış. (Şimdiye kadar gerçek şeytanlar burnumdan akmadı.)
Keith Thompson

1
bana çatal bombaları öğrettiğin için teşekkürler - özyineleme kavramaya çalışırken buna yakın şeyler yaptım :)
ChrisD

2
bilimsel elektronik, modern elektroniklerle yangın hala mümkündür.
Mooing Duck

25

Genel olarak, bugünün İşletim Sistemleri (yine de popüler olanlar) sanal bellek yöneticisi kullanarak korumalı bellek bölgelerindeki tüm uygulamaları çalıştırır. Prosesinize atanmış / tahsis edilmiş bölge (ler) dışındaki GERÇEK alanda bulunan bir yere basitçe okumak veya yazmak için çok kolay KOLAY (sözde) olmadığı ortaya çıkıyor.

Doğrudan cevaplar:

1) Okuma neredeyse hiçbir zaman başka bir sürece doğrudan zarar vermez, ancak bir programı / işlemi şifrelemek, şifresini çözmek veya doğrulamak için kullanılan bir KEY değerini okursanız, dolaylı olarak bir işleme zarar verebilir. Okuduğunuz verilere dayalı kararlar alıyorsanız, sınırların dışında okumak, kodunuz üzerinde bir miktar olumsuz / beklenmedik etki yaratabilir.

2) Bir bellek adresi tarafından erişilebilen bir losyona yazarak bir şeyi gerçekten ZARAR ETMENizin tek yolu, yazdığınız bellek adresinin aslında bir donanım kaydı (aslında veri depolama için değil, bir parçayı kontrol etmek için olan bir konum) RAM konumu değil). Aslında, yeniden yazılamayan (veya bu nitelikteki bir şey) bir kerelik programlanabilir bir konum yazmadıkça, normalde bir şeye zarar vermezsiniz.

3) Genellikle hata ayıklayıcıdan çalıştırıldığında kod hata ayıklama modunda çalışır. Hata ayıklama modunda çalıştırmak, uygulama dışında veya düpedüz yasadışı olarak kabul edilen bir şey yaptığınızda kodunuzu daha hızlı durdurma eğilimindedir (ancak her zaman değil).

4) Asla makro kullanmayın, zaten dizi dizin sınırlarını kontrol eden veri yapılarını kullanmayın.

EK Yukarıdaki bilgilerin gerçekten sadece bellek koruma pencerelerine sahip bir işletim sistemi kullanan sistemler için olduğunu eklemeliyim. Eğer bellek koruma pencereleri (veya sanal adresli pencereler) olmayan bir gömülü sistem, hatta işletim sistemi (gerçek zamanlı ya da diğer) kullanan bir sistem için kod yazıyorsanız, bellek okuma ve yazmada çok daha dikkatli olunmalıdır. Ayrıca bu durumlarda güvenlik sorunlarını önlemek için her zaman GÜVENLİ ve GÜVENLİ kodlama uygulamaları kullanılmalıdır.


4
Güvenli kodlama uygulamaları daima kullanılmalıdır.
Nik Bougalis

3
Çok özel istisnalar yakalamak ve onlardan nasıl kurtarılacağını bilmek sürece deneyin / catch buggy kodu için kullanmanızı öneririz. Yakalama (...), buggy koduna ekleyebileceğiniz en kötü şeydir.
Eugene

1
@NikBougalis - Tamamen katılıyorum, ancak işletim sistemi bellek koruması / sanal adres boşlukları içermiyorsa veya işletim sistemi eksikliği varsa daha fazla ÖNEMLİDİR
trumpetlicks

@Eugene - Benim için bir sorun olduğunu hiç fark etmedim, ama sana katılıyorum, bunu düzenledim mi :-)
trumpetlicks

1) Hasar mı demek istediniz, çünkü sır olarak kalması gereken bir şeyi açığa vuracaktım? 2) Ne demek istediğimi bilmiyorum, ama sanırım sadece dizi sınırları dışındaki yerlere erişmeye çalışırken RAM'e erişiyorum?
ChrisD

9

Sınırların kontrol edilmemesi, güvenlik delikleri de dahil olmak üzere çirkin yan etkilere neden olabilir. Çirkin olanlardan biri keyfi kod yürütmedir . Klasik örnekte: sabit boyutlu bir diziniz varsa ve strcpy()oraya kullanıcı tarafından sağlanan bir dizgi koymak için kullanıyorsanız , kullanıcı size arabellekten taşan ve CPU'nun işleviniz olduğunda geri dönmesi gereken kod adresi de dahil olmak üzere diğer bellek konumlarının üzerine yazan bir dize verebilir bitirir.

Bu, kullanıcılarınızın size programınızın temelde arama yapmasına neden olacak bir dize gönderebileceği anlamına gelir exec("/bin/sh"); bu, onu tüm verilerinizi hasat etmek ve makinenizi botnet düğümüne dönüştürmek de dahil olmak üzere sisteminizde istediği her şeyi yürütmek üzere kabuk haline getirir.

Bunun nasıl yapılabileceğiyle ilgili ayrıntılar için Eğlence ve Kâr Yığını Smashing konusuna bakın .


Sınırları aşan dizi öğelerine erişmemem gerektiğini biliyorum, bu noktayı güçlendirdiğiniz için teşekkürler. Ama soru şu ki, programıma her türlü zararı vermenin yanı sıra, yanlışlıkla programımın belleğinin ötesine ulaşabilir miyim? Ve OSX'te kastediyorum.
Mart'ta ChrisD

@ChrisD: OS X modern bir işletim sistemidir, bu nedenle size tam bellek koruması sağlar. Örneğin, programınızın yapmasına izin verilenlerle sınırlı olmamalısınız. Bu, diğer işlemlerle uğraşmayı içermemelidir (kök ayrıcalıkları altında çalışmıyorsanız).
che

Ben halka 0 ayrıcalıkları altında söylemek istiyorum, kök olanları değil.
Ruslan

Daha da ilginç olanı, hiper-modern derleyiciler kod çalışır okumak için eğer karar verebilir olup foo[0]aracılığıyla foo[len-1]daha önce bir çek kullandıktan sonra lenyürütmek veya kod parçası atlamak birine dizi uzunluğu karşı, derleyici bile koşulsuz bu diğer kod çalıştırmasına çekinmeyin uygulama diziyi geçtikten sonra depolamaya sahipse ve okuma efektleri iyi huylu olurdu, ancak diğer kodu çağırmanın etkisi olmazdı.
supercat

8

Sen yaz:

Bir çok 'her şey olabilir' okudum, 'segmentasyon en az kötü sorun olabilir', 'sabit diskiniz pembeye dönüşebilir ve tek boynuzlu atlar pencerenizin altında şarkı söylüyor olabilir', hepsi güzel, ama gerçekte tehlike nedir?

Bunu şu şekilde söyleyelim: bir silah yükleyin. Belirli bir amaç ve ateş olmadan pencerenin dışına doğrultun. Tehlike nedir?

Sorun bilmiyor olmanız. Kodunuz, programınızı kilitleyen bir şeyin üzerine yazıyorsa, tanımlanmış bir duruma getireceği için sorun yoktur. Ancak çökmezse sorunlar ortaya çıkmaya başlar. Hangi kaynaklar programınızın kontrolü altındadır ve bunlar için ne yapabilir? Hangi kaynaklar programınızın kontrolünü ele geçirebilir ve onlara ne yapabilir? Böyle bir taşma nedeniyle en az bir önemli sorun biliyorum. Sorun, bir üretim veritabanı için alakasız dönüşüm tablosunu bozan, görünüşte anlamsız bir istatistik işlevindeydi. Sonuç, sonrasında çok pahalı bir temizlik oldu. Aslında, bu sorun sabit diskleri biçimlendirirse çok daha ucuz ve kullanımı daha kolay olurdu ... başka bir deyişle: pembe tek boynuzlu atlar en az sorununuz olabilir.

İşletim sisteminizin sizi koruyacağı fikri iyimser. Mümkünse sınırların dışında yazmaktan kaçının.


tamam, tam olarak korktuğum şey buydu. 'Sınırları yazmaktan kaçınmaya çalışacağım' ama son birkaç aydır neler yaptığımı görünce kesinlikle çok şey yapacağım. Güvenli bir uygulama yöntemi olmadan programlamada nasıl bu kadar başarılı oldunuz?
ChrisD

3
Kim bir şey güvenli olduğunu söyledi;)
Udo Klein

7

Programınızı root veya başka bir ayrıcalıklı kullanıcı olarak çalıştırmamak sisteminizin hiçbirine zarar vermez, bu nedenle bu genellikle iyi bir fikir olabilir.

Verileri rasgele bellek konumuna yazarak, her işlem kendi bellek alanında çalıştığı için bilgisayarınızda çalışan başka bir programa doğrudan "zarar vermezsiniz".

İşleminize tahsis edilmemiş bir belleğe erişmeye çalışırsanız, işletim sistemi programınızın bir segmentasyon hatasıyla yürütülmesini durduracaktır.

Bu nedenle doğrudan (root olarak çalışmadan ve / dev / mem gibi dosyalara doğrudan erişmeden), programınızın işletim sisteminizde çalışan diğer programlara müdahale etme tehlikesi yoktur.

Yine de - ve muhtemelen tehlike açısından duyduğunuz şey budur - rastgele verileri rasgele bellek konumlarına yanlışlıkla kazara yazarak zarar verebileceğiniz her şeye zarar verebilirsiniz.

Örneğin, programınız, programınızın herhangi bir yerinde saklanan bir dosya adıyla verilen belirli bir dosyayı silmek isteyebilir. Yanlışlıkla, dosya adının bulunduğu konumun üzerine yazarsanız, bunun yerine çok farklı bir dosyayı silebilirsiniz.


1
Eğer varsa edilir kök (veya başka ayrıcalıklı kullanıcı) olarak çalışan, olsa da, dikkat. Arabellek ve dizi taşmaları yaygın bir kötü amaçlı yazılım istismarıdır.
John Bode

aslında tüm günlük bilgisayarlarım için kullandığım hesap bir yönetici hesabı değil (benim sistemim olduğu için OSX terminolojisini kullanıyorum). HERHANGİ BİR bellek konumu ayarlamaya çalışarak bir şeye zarar veremeyeceğimi mi söylüyorsun? Bu gerçekten harika bir haber!
ChrisD

Daha önce de belirtildiği gibi, kazara yapabileceğiniz en kötü zarar, kullanıcı olarak yapabileceğiniz en kötü zarardır. % 100 emin olmak istiyorsanız verilerinizden hiçbirini yok etmeyin, muhtemelen bilgisayarınıza farklı bir hesap eklemek ve bununla deneme yapmak isteyebilirsiniz.
mikyra

1
@mikyra: Bu sadece sistemin koruyucu mekanizmaları% 100 etkili olduğunda geçerlidir. Kötü amaçlı yazılımın varlığı, her zaman buna güvenemeyeceğinizi gösterir. (Bunun endişelenmeye değer olduğunu iddia etmek istemiyorum; bir programın yanlışlıkla kötü amaçlı yazılım tarafından kullanılan aynı güvenlik deliklerinden yararlanması olasıdır, ancak pek olası değildir .)
Keith Thompson

1
Buradaki liste şunları içerir: Güvenilmeyen kaynaklardan çalışan kod. Sadece ne olduğunu okumadan güvenlik duvarının herhangi bir açılır penceresindeki Tamam düğmesine tıklamanız veya istenen ağ bağlantısı kurulamıyorsa tamamen kapatmanız yeterlidir. Şüpheli kaynaklardan gelen en yeni kesmekle ikili dosyaları yamalamak. Sahibi, herhangi bir hırsızı her iki kolu ve ekstra güçlü müstahkem kapıları açık olarak gönüllü olarak davet ederse kasanın hatası değildir.
mikyra

4

NSArrayObjective-C'deki belirli bir bellek bloğu atanır. Dizinin sınırlarını aşmak, diziye atanmamış belleğe erişeceğiniz anlamına gelir. Bu şu anlama gelir:

  1. Bu bellek herhangi bir değere sahip olabilir. Veri türünüze göre verilerin geçerli olup olmadığını bilmenin bir yolu yoktur.
  2. Bu bellek özel anahtarlar veya diğer kullanıcı kimlik bilgileri gibi hassas bilgiler içerebilir.
  3. Bellek adresi geçersiz veya korumalı olabilir.
  4. Başka bir program veya iş parçacığı tarafından erişildiği için belleğin değeri değişebilir.
  5. Diğer şeyler, bellek eşlemeli bağlantı noktaları gibi bellek adres alanını kullanır.
  6. Bilinmeyen bellek adresine veri yazmak programınızı kilitleyebilir, işletim sistemi bellek alanının üzerine yazabilir ve genellikle güneşin patlamasına neden olabilir.

Programınızın bakış açısından, kodunuzun bir dizinin sınırlarını ne zaman aştığını bilmek istersiniz. Bu, bilinmeyen değerlerin döndürülmesine neden olarak uygulamanızın kilitlenmesine veya geçersiz veriler sağlamasına neden olabilir.


NSArrayssınırların dışında istisnalar var. Ve bu sorular C dizisi hakkında.
DrummerB

Gerçekten C dizilerini kastediyordum. NSArray olduğunu biliyorum, ama şimdilik egzersizlerimin çoğu C
ChrisD

4

Kodunuzu test ederken Valgrind'dekimemcheck aracı kullanmayı denemek isteyebilirsiniz - yığın çerçevesi içinde ayrı ayrı dizi sınırları ihlallerini yakalamaz, ancak ince, daha geniş hale getirecek olanlar da dahil olmak üzere diğer birçok bellek sorunu yakalamalıdır. tek bir fonksiyonun kapsamı dışındaki problemler.

Kılavuzdan:

Memcheck bir bellek hata dedektörüdür. C ve C ++ programlarında sık karşılaşılan aşağıdaki sorunları algılayabilir.

  • Hafızaya erişmemeniz gerekir; örneğin, aşırı ve az çalışan yığın blokları, yığının üstünü ve daha sonra serbest bırakıldıktan sonra hafızaya erişmemeniz gerekir.
  • Tanımsız değerler, yani başlatılmamış veya diğer tanımlanmamış değerlerden türetilen değerler kullanılması.
  • Çift boşaltma yığın blokları gibi yığın belleğin yanlış boşaltılması veya serbest / sil / sil [] yerine malloc / new / new [] ile eşleşmeyen kullanım
  • Memcpy ve ilgili fonksiyonlarda örtüşen src ve dst işaretçileri.
  • Bellek sızdırıyor.

ETA: Kaz'ın cevabının dediği gibi, her derde deva değil ve özellikle heyecan verici erişim kalıpları kullanırken her zaman en yararlı çıktıyı vermiyor .


XCode Analizörünün çoğunun bulacağından şüphelenir miyim? ve benim sorum bu hataları nasıl bu kadar çok değil, ama hala bu hataları olan bir program yürütmek benim programa tahsis edilmemiş bellek için tehlikeli. Hataları görmek için programı yürütmek zorunda
kalacağım

3

Sistem düzeyinde programlama veya gömülü sistem programlama yaparsanız, rastgele bellek konumlarına yazarsanız çok kötü şeyler olabilir. Daha eski sistemler ve birçok mikro denetleyici bellek eşlemeli GÇ kullanır, bu nedenle bir çevresel kayıtla eşlenen bir bellek konumuna yazmak, özellikle eşzamansız olarak yapılırsa, tahribatı azaltabilir.

Bir örnek flash belleği programlamaktır. Bellek yongalarındaki programlama modu, yonganın adres aralığındaki belirli konumlara belirli bir değer dizisi yazarak etkinleştirilir. İşlem devam ederken başka bir işlem çipteki başka bir konuma yazmak olsaydı, programlama döngüsünün başarısız olmasına neden olur.

Bazı durumlarda donanım adresleri etrafına sarar (en önemli bit / bayt adresi göz ardı edilir), bu nedenle fiziksel adres alanının sonunun ötesinde bir adrese yazmak aslında verilerin tam olarak ortasında yazılmasına neden olur.

Ve son olarak, MC68000 gibi eski CPU'lar sadece donanım sıfırlamasının tekrar başlayabileceği noktaya kadar kilitlenebilir. Birkaç on yıl boyunca onlar üzerinde çalışmadım ama bir istisna işlemeye çalışırken bir otobüs hatası (var olmayan bellek) ile karşılaştığında, donanım sıfırlama iddia edilene kadar duracağını düşünüyorum.

En büyük tavsiyem bir ürün için açık bir fiş, ancak kişisel bir ilgim yok ve onlarla hiçbir şekilde ilişkili değilim - ancak güvenilirliğin kritik olduğu birkaç yıllık C programlama ve gömülü sistemlere dayanarak Gimpel'in PC'si Lint sadece bu tür hataları tespit etmekle kalmaz, sürekli olarak kötü alışkanlıklar hakkında size zarar vererek daha iyi bir C / C ++ programcısı yapar .

Birinden bir kopyasını alabiliyorsanız, MISRA C kodlama standardını da okumanızı tavsiye ederim. Yakın zamanda bir tane görmedim ama siz olde günlerinde, neleri kapsadıkları / yapmamanız gerektiğine dair iyi bir açıklama yaptılar.

Senin hakkında bilmiyorum, ama herhangi bir uygulamadan 2 veya 3. kez bir coredump veya hangup aldım, hangi şirketi ürettiğime dair düşüncem yarı yarıya azalıyor. 4. veya 5. kez ve paket ne olursa olsun, raf malzemesi haline gelir ve paketin / diskin ortasından tahta bir kazık sürüyorum, sadece bana asla uğramamasını sağlamak için geldi.


Sisteme bağlı olarak, aralık dışı okumalar da öngörülemeyen davranışları tetikleyebilir veya iyi huylu olabilir, ancak aralık dışı yüklerdeki iyi huylu donanım davranışı iyi huylu derleyici davranışı anlamına gelmez.
supercat

2

Kasıtlı olmayan bir C kodu dışında bir dizinin sonuna geçmiş erişen kod üreten bir DSP çip için bir derleyici ile çalışıyorum!

Bunun nedeni, döngülerin bir yinelemenin sonu bir sonraki yineleme için bazı verileri önceden alacak şekilde yapılandırılmış olmasıdır. Bu nedenle, son yinelemenin sonunda önceden getirilmiş olan veri asla kullanılmaz.

Bu şekilde C kodu yazmak, tanımlanmamış davranışı gerektirir, ancak bu yalnızca standart bir belgeden maksimum taşınabilirlikle ilgilenen bir formalitedir.

Daha sık olmamakla birlikte, sınırların dışına erişen bir program akıllıca optimize edilmez. Sadece adamcağız. Kod bir miktar çöp değeri getirir ve yukarıda bahsedilen derleyicinin optimize edilmiş döngülerinin aksine, kod daha sonra sonraki hesaplamalarda değeri kullanır , böylece imi bozar.

Bu gibi hataları yakalamaya değer ve bu yüzden sadece bu nedenle bile davranışı tanımsız hale getirmeye değer: böylece çalışma zamanı "main.c satır 42'de dizi taşması" gibi bir tanılama mesajı üretebilir.

Sanal belleğe sahip sistemlerde, izleyen adres sanal belleğin eşlenmemiş alanında olacak şekilde bir dizi atanabilir. Erişim daha sonra programı bombalayacaktır.

Bir kenara, C'de bir dizinin sonundan bir işaretçi oluşturmamıza izin verildiğini unutmayın. Ve bu işaretçi, bir dizinin iç kısmıyla herhangi bir işaretçiden daha büyük karşılaştırmak zorundadır. Bu, bir C uygulamasının bir diziyi belleğin sonuna yerleştiremeyeceği, bir artı adresin etrafa sarılacağı ve dizideki diğer adreslerden daha küçük görüneceği anlamına gelir.

Bununla birlikte, başlatılmamış veya sınır dışı değerlere erişim, maksimum düzeyde taşınabilir olmasa bile, bazen geçerli bir optimizasyon tekniğidir. Bu nedenle, Valgrind aracının bu erişim gerçekleştiğinde başlatılmamış verilere erişimi raporlamamasının nedeni, ancak değer daha sonra programın sonucunu etkileyebilecek bir şekilde kullanıldığında. "Xxx'de koşullu dal: nnn başlatılmamış değere bağlıdır" gibi bir tanı alırsınız ve kökenini izlemek bazen zor olabilir. Bu tür tüm erişimler hemen yakalanırsa, derleyici için optimize edilmiş kodun yanı sıra elle optimize edilmiş koddan kaynaklanan çok sayıda yanlış pozitif olurdu.

Bundan bahsetmişken, Linux'a taşındığında ve Valgrind altında çalıştırıldığında bu hataları veren bir satıcıdan bazı codec ile çalışıyordum. Ancak satıcı beni sadece birkaç kişinin bitinkullanılan değerin büyük kısmı başlatılmamış bellekten geldi ve bu bitler mantık tarafından dikkatle önlendi. Sadece değerin iyi bitleri kullanılıyordu ve Valgrind bireysel biti takip etme yeteneğine sahip değildi. Başlatılmamış materyal, kodlanmış bir bit veri akışının sonunu geçen bir kelimeyi okumaktan geldi, ancak kod akışta kaç bit olduğunu biliyor ve gerçekte olduğundan daha fazla bit kullanmayacak. Bit akışı dizisinin sonunun ötesindeki erişim DSP mimarisine zarar vermediğinden (diziden sonra sanal bellek yoktur, bellek eşlemeli bağlantı noktası yoktur ve adres sarılmaz) geçerli bir optimizasyon tekniğidir.

"Tanımlanmamış davranış" gerçekten fazla bir şey ifade etmez, çünkü ISO C'ye göre, basitçe C standardında tanımlı olmayan bir başlık eklemek veya programın kendisinde veya C standardında tanımlı olmayan bir fonksiyon çağırmak tanımsız örneklerdir davranışı. Tanımsız davranış "gezegendeki hiç kimse tarafından tanımlanmamış" anlamına gelmez "sadece" ISO C standardı tarafından tanımlanmamıştır. Ama tabii ki, bazen tanımsız davranış gerçekten edilir kesinlikle herkes tarafından tanımlanmamış.


Ayrıca, Standartta verilen tüm uygulama sınırlarını vergilendirmesine rağmen, belirli bir uygulamanın doğru şekilde işlediği en az bir program olması şartıyla, bu uygulama kısıtlama ihlallerinden arınmış başka bir programla beslendiğinde keyfi davranabilir ve " Uysal". Sonuç olarak, C programlarının% 99,999'u (platformun "bir programı" dışında herhangi bir şey), Standardın hiçbir gereklilik getirmediği davranışlara dayanır.
supercat

1

Kendi programınızın yanı sıra, hiçbir şeyi kıracağınızı düşünmüyorum, en kötü durumda, çekirdeğin işlemlerinize atamadığı bir sayfaya karşılık gelen bir bellek adresini okumaya veya yazmaya çalışacaksınız, uygun istisna oluşturacaksınız ve öldürülmek (yani, senin sürecin).


3
..Ne? Daha sonra kullanılan bazı değişkenleri saklamak için kullanılan kendi işleminizde belleğin üzerine yazmaya ne dersiniz ... şimdi gizemli bir şekilde değerini değiştirdi! Bu böceklerin izini sürmek çok eğlenceli, sizi temin ederim. Bir segfault en iyi sonuç olacaktır. -1
Ed

2
Demek istediğim, kendi programının yanı sıra diğer süreçleri de "kırmayacak;)
jbgs

Gerçekten kendi programımı bozup bozmadığım umurumda değil. Ben sadece öğreniyorum, benim dizi sınırının dışında bir şey erişirseniz program zaten yanlıştır. Kreasyonlarımda hata ayıklarken başka bir şeyi kırma riskleri hakkında gittikçe daha fazla endişeleniyorum
ChrisD

Mesele şu: Bana atanmamış belleğe erişmeye çalışırsam, işlemimin öldürüleceğinden emin olabilir miyim? (OSX'te olmak)
ChrisD

3
Yıllar önce, beceriksiz bir C programcısıydım. Yüzlerce kez sınırları dışında dizilere eriştim. İşletim sistemi tarafından öldürülme sürecimin yanı sıra hiçbir şey olmadı.
jbgs
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.