2010-06-29 16 views
5

Mam następujących funkcji jako konstruktora dla klasy:C++ Mapa daje błąd Bus gdy próbuje ustawić wartość

template<typename T> 
void Pointer<T>::Pointer(T* inPtr) 
{ 
    mPtr = inPtr; 
    if (sRefCountMap.find(mPtr) == sRefCountMap.end()) { 
    sRefCountMap[mPtr] = 1; 
    } else { 
    sRefCountMap[mPtr]++; 
    } 
} 

Oto definicja mapie:

static std::map<T*, int> sRefCountMap; 

otrzymuję Błąd magistrali czasami, gdy ten kod jest uruchamiany:

#0 0x95110fc0 in std::_Rb_tree_decrement() 
#1 0x00017ccc in std::_Rb_tree_iterator<std::pair<Language::Value* const, int> >::operator-- (this=0xbfffe014) at stl_tree.h:196 
#2 0x0001b16c in std::_Rb_tree<Language::Value*, std::pair<Language::Value* const, int>, std::_Select1st<std::pair<Language::Value* const, int> >, std::less<Language::Value*>, std::allocator<std::pair<Language::Value* const, int> > >::insert_unique (this=0x2a404, [email protected]) at stl_tree.h:885 
#3 0x0001b39c in std::_Rb_tree<Language::Value*, std::pair<Language::Value* const, int>, std::_Select1st<std::pair<Language::Value* const, int> >, std::less<Language::Value*>, std::allocator<std::pair<Language::Value* const, int> > >::insert_unique (this=0x2a404, __position={_M_node = 0x2a408}, [email protected]) at stl_tree.h:905 
#4 0x0001b5a0 in __gnu_norm::map<Language::Value*, int, std::less<Language::Value*>, std::allocator<std::pair<Language::Value* const, int> > >::insert (this=0x2a404, position={_M_node = 0x2a408}, [email protected]) at stl_map.h:384 
#5 0x0001b6e0 in __gnu_norm::map<Language::Value*, int, std::less<Language::Value*>, std::allocator<std::pair<Language::Value* const, int> > >::operator[] (this=0x2a404, [email protected]) at stl_map.h:339 

Dzięki.

+4

dlaczego nie po prostu zrobić sRefCountMap [mPtr] ++? Jeśli nie istnieje, zostanie uruchomione i uruchomione na 0 ... – Goz

+2

Czy masz jakieś statyczne instancje 'Pointer'? Można je zbudować przed mapą. –

+1

Czy ten program jest jednowątkowy, czy też kilka różnych wątków korzysta z sRefCountMap? Zastanawiam się, czy możemy wykluczyć błędy wątku. –

Odpowiedz

6

Z twoich komentarzy wynika, że ​​zainicjalizowałeś statyczne Pointer. Najprawdopodobniej oznacza to, że napotkano "statyczną kolejność inicjalizacji" - jeśli dwa statyczne obiekty znajdują się w różnych jednostkach kompilacji, to nie jest zdefiniowana kolejność, w której są inicjowane. Tak więc, jeśli konstruktor jednego zależy od drugiego, który już jest zainicjowany, możesz uciec, albo nie. Prawo Sod nakazuje, aby kod działał podczas testowania, a następnie tajemniczo łamał się po jego wdrożeniu.

Najlepszym rozwiązaniem jest unikanie obiektów statycznych; rzadko są dobrym pomysłem.

Inną możliwością jest leniwy instancji, coś takiego:

typedef std::map<T*, int> RefCountMap; 

static RefCountMap& GetRefCountMap() 
{ 
    static RefCountMap map; 
    return map; 
} 

To może mieć problemy na jego własne; Jest gwarantowane, że zostanie skonstruowany, zanim zostanie użyty, ale może zostać zniszczony, zanim skończysz, jeśli dostępny będzie statyczny destruktor i mogą wystąpić problemy z bezpieczeństwem wątków. Szczegółowe informacje można znaleźć w wielu dyskusjach dotyczących wzorca Singleton, który wymaga statycznej instancji. Singletony w C++ to cały świat bólu, najlepiej unikany, jeśli to możliwe.

+0

FWIW, to tylko miła globalna zmienna, a nie singleton (nie uniemożliwiasz tworzenia kolejnych 'RefCountMap's). Uważam jednak, że to globalne rozwiązanie jest o wiele lepsze od singletonu. – GManNickG

+0

@GMan: masz rację; Zmontowałem, aby poprawić terminologię. –

1

Prawdopodobnie uszkodziłeś kupkę w innym miejscu w swoim programie. Uruchom program za pomocą debuggera pamięci (np. Valgrind) i znajdź, gdzie występuje uszkodzenie.

+3

Odpowiedź Mike'a jest bardziej prawdopodobna teraz, gdy powiedziałeś, że to statyczny "Pointer". Jednak w przypadku braku inicjalizacji statycznej tajemnicza awaria w standardowej klasie lub funkcji biblioteki jest prawie zawsze problemem korupcji sterty. –

Powiązane problemy