Segmentasyon hatası nedir? C ve C ++ 'da farklı mıdır? Segmentasyon hataları ve sarkan işaretçiler arasında nasıl bir ilişki vardır?
NullPointerException
.
Segmentasyon hatası nedir? C ve C ++ 'da farklı mıdır? Segmentasyon hataları ve sarkan işaretçiler arasında nasıl bir ilişki vardır?
NullPointerException
.
Yanıtlar:
Segmentasyon hatası, “size ait olmayan” belleğe erişmenin neden olduğu belirli bir hata türüdür. Bu, belleği bozmanızı ve hata ayıklaması zor bellek hataları getirmenizi engelleyen bir yardımcı mekanizmadır. Bir segfault aldığınızda, bellekte yanlış bir şey yaptığınızı biliyorsunuzdur - daha önce serbest bırakılmış olan değişkene erişme, belleğin salt okunur bir bölümüne yazma, vb. bellek yönetimi, C ve C ++ segfaultlar arasında temel bir fark yoktur.
En azından C (++) gibi alt düzey dillerde segfault almanın birçok yolu vardır. Segfault almanın yaygın bir yolu, boş bir göstergenin kaldırılmasıdır:
int *p = NULL;
*p = 1;
Belleğin salt okunur olarak işaretlenmiş bir bölümüne yazmaya çalıştığınızda başka bir segfault gerçekleşir:
char *str = "Foo"; // Compiler marks the constant string as read-only
*str = 'b'; // Which means this is illegal and results in a segfault
İşaretçi sarkıyor, artık burada olmayan bir şeye işaret ediyor:
char *p = NULL;
{
char c;
p = &c;
}
// Now p is dangling
İşaretçi , blok bittikten sonra var olmayan p
karakter değişkenine işaret ettiği için sarkar c
. Ve sarkan bir işaretçi (gibi *p='A'
) atlatmaya çalıştığınızda muhtemelen bir segfault elde edersiniz.
c
, bunun yerel olduğunu anlamanız gerekir , bu sonra yığın üzerine itilmiş ve sonra {
dışarı pop-ed anlamına gelir }
. sarkan ibre sadece yığının dışında olan bir ofset için bir referanstır. bu yüzden basit bir programda değiştirmek asla herhangi bir segfault tetiklemeyecektir. Öte yandan, daha karmaşık bir kullanım durumunda segfault'a yol açabilir, burada diğer fonksiyon çağrıları yığının büyümesine ve sarkan işaretçinin işaret ettiği verileri içermesine neden olabilir. Bu verilere yazmak (yerel varyasyonlar) tanımlanmamış davranışa (segfault & Co) yol açacaktır
SIGSEGV
çevirdim, bu yüzden böyle bir sinyalin yığınla karışmasını beklemeyeceğim.
Segmentasyon hatasına doğrudan başka bir işlem belleğine (bazen duyduğum şey) erişmekten kaynaklanmadığını belirtmek gerekir, çünkü bu mümkün değildir. Sanal bellek ile her işlemin kendi sanal adres alanı vardır ve işaretçinin herhangi bir değerini kullanarak başka bir adrese erişmenin bir yolu yoktur. Bunun istisnası, aynı fiziksel adres alanı olan (muhtemelen) farklı sanal adreslere ve her işlemde aynı şekilde eşlenen çekirdek belleğe (syscall'da TLB'nin kızarmasını önlemek için) eşlenen paylaşımlı kütüphaneler olabilir. Ve shmat gibi şeyler;) - bunlar 'dolaylı' erişim olarak saydıklarım. Bununla birlikte, genellikle süreç kodundan çok uzakta bulunduklarını kontrol edebiliriz ve genellikle bunlara erişebiliriz (bu yüzden oradalar,
Yine de, kendi (işlem) belleğimize uygunsuz bir şekilde erişilmesi durumunda segmentasyon hatası meydana gelebilir (örneğin yazılamaz alana yazmaya çalışıyorum). Ancak bunun en yaygın nedeni, sanal adres alanının fiziksel olarak eşlenmemiş kısmına erişimdir .
Ve tüm bunlar sanal bellek sistemleri ile ilgili.
Segmentasyon hatası, işlemin tanımlayıcı tablosunda listelemediği bir sayfa isteği veya listelediği bir sayfa için geçersiz bir istek (örneğin, salt okunur bir sayfada yazma isteği) nedeniyle oluşur.
Sarkan bir işaretçi, geçerli bir sayfayı gösterebilen veya göstermeyen, ancak "beklenmeyen" bir bellek bölümüne işaret eden bir işaretçidir.
Dürüst olmak gerekirse, diğer posterlerin de belirttiği gibi, Wikipedia'nın bu konuda çok iyi bir makalesi var, bu yüzden oraya bir göz atın. Bu tür hatalar çok yaygındır ve genellikle Erişim İhlali veya Genel Koruma Hatası gibi başka şeyler denir.
C, C ++ veya işaretçilere izin veren başka bir dilde farklı değildirler. Bu tür hatalara genellikle
Wikipedia'ya göre:
Bir program, erişmesine izin verilmeyen bir bellek konumuna erişmeye veya bir bellek konumuna izin verilmeyen bir şekilde erişmeye çalıştığında (örneğin, salt okunur bir konuma yazmaya çalıştığında) bir bölümleme hatası oluşur veya işletim sisteminin bir kısmının üzerine yazmak için).
Segmentasyon hatasına ayrıca donanım arızaları, bu durumda RAM bellekleri neden olur. Bu daha az yaygın nedendir, ancak kodunuzda bir hata bulamazsanız, belki de bir memtest size yardımcı olabilir.
Bu durumda çözüm, RAM'i değiştirin.
Düzenle:
Burada bir referans var: Donanımdan bölümleme hatası
Segmentasyon hatası , bir işlem (bir programın çalışan örneği) başka bir işlem tarafından kullanılan veya var olmayan (geçersiz) bellek adresine erişen salt okunur bellek adresine veya bellek aralığına erişmeye çalıştığında oluşur. Sarkan Referans (işaretçi) sorunu , içeriği bellekten zaten silinmiş olan bir nesneye veya değişkene erişmeye çalışmanın, örneğin:
int *arr = new int[20];
delete arr;
cout<<arr[1]; //dangling problem occurs here
Wikipedia'nın Segmentation_fault sayfası, bunun nedenlerini ve nedenlerini işaret ederek çok güzel bir açıklamaya sahiptir. Ayrıntılı bir açıklama için wiki'ye bir göz atın.
Hesaplamada, bir segmentasyon hatası (genellikle segfault'a kısaltılır) veya erişim ihlali, bellek korumalı bir donanım tarafından oluşturulan ve işletim sistemini (OS) bellek erişim ihlali hakkında bilgilendiren bir hatadır.
Bir segmentasyon hatasının tipik nedenleri şunlardır:
Bunlara genellikle geçersiz bellek erişimi ile sonuçlanan programlama hataları neden olur:
Başlatılmamış bir işaretçiyi silme veya atama (rasgele bellek adresini gösteren vahşi işaretçi)
Serbest bırakılmış bir işaretçiyi silme veya atama (serbest bırakılmış / serbest bırakılmış / silinmiş belleğe işaret eden sarkan işaretçi)
Bir arabellek taşması.
Bir yığın taşması.
Doğru derlenmeyen bir program yürütülmeye çalışılıyor. (Bazı derleyiciler, derleme zamanı hatalarına rağmen yürütülebilir bir dosya çıkarır.)
Basit bir ifadeyle: segmentasyon hatası, programa, programa bir sinyal erişimi göndererek geçersiz bellek erişimi algıladığını ve belleğin bozulmasını önlemek için programı erken sonlandırdığını söyler.
"Segmentasyon hatası", erişiminiz olmayan belleğe erişmeye çalıştığınız anlamına gelir.
İlk sorun ana argümanlarınızdır. Ana işlev olmalıdır int main(int argc, char *argv[])
ve argv [1] 'e erişmeden önce argc öğesinin en az 2 olduğunu kontrol etmelisiniz.
Ayrıca, printf'e bir float geçirdiğinizden (bu arada, printf'e geçerken bir çifte dönüştürülür),% f format belirleyicisini kullanmalısınız. % S biçim belirteci dizeler içindir ('\ 0' sonlandırılmış karakter dizileri).
Bir program var olmayan bir bellek konumuna erişmeye veya bir bellek konumuna izin verilmeyen bir şekilde erişmeye çalıştığında bir segmentasyon hatası veya erişim ihlali oluşuyor.
/* "Array out of bounds" error
valid indices for array foo
are 0, 1, ... 999 */
int foo[1000];
for (int i = 0; i <= 1000 ; i++)
foo[i] = i;
Burada i [1000] mevcut değil, bu yüzden segfault oluşur.
Segmentasyon hatasının nedenleri:
it arise primarily due to errors in use of pointers for virtual memory addressing, particularly illegal access.
De-referencing NULL pointers – this is special-cased by memory management hardware.
Attempting to access a nonexistent memory address (outside process’s address space).
Attempting to access memory the program does not have rights to (such as kernel structures in process context).
Attempting to write read-only memory (such as code segment).
Yanıtlarda "Segmentasyon hatası" nın birkaç iyi açıklaması vardır, ancak segmentasyon hatası ile genellikle bellek içeriğinin bir dökümü olduğundan, Segmentasyon hatası (çekirdek dökümü) içindeki "çekirdek dökümü" kısmı arasındaki ilişkinin ve bellek:
Yaklaşık 1955'ten 1975'e kadar - yarıiletken belleğinden önce - bilgisayar belleğindeki baskın teknoloji, bakır tellere asılmış küçük manyetik çörekleri kullandı. Donutlar "ferrit çekirdekler" ve "çekirdek bellek" veya "çekirdek" olarak bilinen ana bellek olarak biliniyordu.
Buradan alındı .
Segmentasyon hatası yeterli tanımları vardır, ben programlama sırasında karşılaştığım, aptalca hatalar görünebilir, ancak çok zaman harcayacak birkaç örnek alıntı istiyorum.
printf'de argumet tipi uyuşmazlığı varken aşağıdaki durumda segmentasyon hatası alabilirsiniz
#include<stdio.h>
int main(){
int a = 5;
printf("%s",a);
return 0;
}
çıktı : Segmentation Fault (SIGSEGV)
bir işaretçiye bellek ayırmayı unuttuğunuzda, ancak kullanmaya çalıştığınızda.
#include<stdio.h>
typedef struct{
int a;
}myStruct;
int main(){
myStruct *s;
/* few lines of code */
s->a = 5;
return 0;
}
çıktı : Segmentation Fault (SIGSEGV)
Basit anlamı, Segmentation fault
size ait olmayan bir hafızaya erişmeye çalışmanızdır. Segmentation fault
görevleri salt okunur bir bellek konumunda okumaya ve / veya yazmaya çalıştığımızda veya belleği boşaltmaya çalıştığımızda oluşur. Başka bir deyişle, bunu bir çeşit bellek bozulması olarak açıklayabiliriz.
Aşağıda programcıların yol açtığı yaygın hatalardan bahsediyorum Segmentation fault
.
scanf()
Yanlış şekilde kullanın (koymayı unuttum &
).int num;
scanf("%d", num);// must use &num instead of num
int *num;
printf("%d",*num); //*num should be correct as num only
//Unless You can use *num but you have to point this pointer to valid memory address before accessing it.
char *str;
//Stored in read only part of data segment
str = "GfG";
//Problem: trying to modify read only memory
*(str+1) = 'n';
// allocating memory to num
int* num = malloc(8);
*num = 100;
// de-allocated the space allocated to num
free(num);
// num is already freed there for it cause segmentation fault
*num = 110;
printf()
ve scanf()
'