2013-02-28 20 views
7

Listemin size() işlevini kullanma girişiminde kodumun kesildiği bir sorunla karşılaştım. Stackoverflow :-) tavsiyesi üzerine segfault'un oluştuğu minimum bir durum oluşturdum (aşağıdaki call inventory.size() üzerinde). Öyle:Kurucudaki dizi ayarı daha sonra başarısızlık demektir

#include <list> 

class Thing {}; 

class Player { 
private: 
    int xpCalcArray[99]; 
    std::list<Thing*> inventory; 

public: 
    Player(); 

    int addToInv(Thing& t); // return 1 on success, 0 on failure 
}; 

Player::Player() { 
    // set up XP calculation array 
    for (int i=1; i<100; i++) { 
    if (i<=10) { 
     xpCalcArray[i] = i*100; 
    } 
    if (i>10 && i<=50) { 
     xpCalcArray[i] = i*1000; 
    } 
    if (i>50 && i<=99) { 
     xpCalcArray[i] = i*5000; 
    } 
    } 
} 

int Player::addToInv(Thing& t) { 
    if (inventory.size() == 52) { 
    return 0; 
    } else { 
     inventory.push_back(&t); 
    } 
    return 1; 
} 

int main(int argc, char *argv[]) { 
    Thing t; 
    Player pc; 
    pc.addToInv(t); 
    return 1; 
} 

Ben Oyuncu cosntructor dizinin kurulmasını kaldırdığınızda, bu çalışıyor fark, bu nedenle bu sorunun görünüyor. Neyi yanlış yapıyorum?

+2

+1: TestCase! Mükemmel! –

cevap

2

Dizininizin sınırları dışında erişiyorsunuz. Bunu yapmak, tanımlanmamış davranışlara neden olur ve bundan sonra gerçekleşen hiçbir şey için mantıklı bir açıklama yoktur. Dizininizin boyutu 99 ve bu nedenle son indeks 98'dir. Ancak, for döngü 99'a kadar çıkmaktadır.

Ya

senin dizi boyutunu 100 yapmak:

int xpCalcArray[100]; 

Veya i < 99 için for koşulunu değiştirin.

4

Dizininize sınırlar dışında erişiyorsunuz, bu da tanımsız davranış ile sonuçlanıyor. Ben 0'dan başlamak Sizin dış döngü

for (int i=0; i<99; i++) { ... } 

Not olmalıdır

if (i>50 && i<=99) { 
    xpCalcArray[i] = i*5000; 
} 

: Bu dizinin

int xpCalcArray[99]; 

için geçerli endeks aralığı 0 98 Burada endeksi 99 erişen etmektir Aslında, ilk öğeye erişmek istediğiniz varsayımıdır. Eğer bir boyutu 100 dizisi kullanmak istediğini Eğer

Ardından, nihai durum

if (i>50) { 
    xpCalcArray[i] = i*5000; 
} 

için basitleştirilmiş olabilir, o zaman int i=0; i<100; arasında

int xpCalcArray[100]; 

sonra döngü gerekir.

+2

Ve açıkçası, biri her yerde yaklaşık 50, 98, 99 ve 100 kodlar yerine * tek bir sabit * kullanacaktır ... –

+0

Hepinize teşekkür ederim. Hamuru. – KHekkus

2

2. → 100 öğelerini (1 → 99'uncu yerine) değiştirmeye çalışarak 99 int s dizininizin üzerine yazıyorsunuz. listeyi kullanmaya çalıştığınızda Senin durumunda

, bunların hepsi, böylece (ama besbelli sizin için bugün doğrudan dizide — her zaman sonra bellekte var) std::list<Thing*> içinde bazı bellek üzerine yazmak olur ve İç üye verileri artık ne olduğunu düşündüğü zaman cehennem kopar.

1

Siz xpCalcArray 0'dan 98'e kadar (99 öğe büyüklüğünde) tanımlanmıştır.

Döngününüz 100'den 100'e kadar 0'dan 99'a kadar gider.

Son döngü döngüsü, mevcut olmayan 99 konumunda xpCalcArray yazıyor. Bu (dolaylı olarak), the answer of Lightness Races in Orbit tarafından gösterildiği gibi segmentasyon hatasına neden olur.

Yani, 1 ile xpCalcArray boyutunu artırmak:

int xpCalcArray[100]; 
+0

Bu bölümleme hatasıyla _indirectly_ sonuçları. Buradaki tek doğrudan sonuç UB'yi çağırıyor. –

+0

Evet haklısınız, nedeninin ek açıklaması mükemmel! – Veger

+0

Kodun istenilen mantığını bilmeden dizinin boyutunu artırmak doğru çözüm değildir. Olabilirdi, ama emin olamayız. – juanchopanza