2010-06-29 15 views
5

que tiene la siguiente función que el constructor para una clase:C++ Mapa produce un error de bus cuando se trata de establecer un valor

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

Esta es la definición para el mapa:

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

consigo un error de bus a veces cuando se ejecuta este código:

#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 

Thanks.

+4

¿por qué no simplemente hacer sRefCountMap [mPtr] ++? Si no existe, cobrará vida e inicializará en 0 ... – Goz

+2

¿Tiene instancias estáticas de 'Puntero'? Podrían construirse antes del mapa. –

+1

¿Este programa tiene un solo subproceso o varios subprocesos diferentes usan sRefCountMap? Me pregunto si podemos descartar errores de hilo. –

Respuesta

6

De sus comentarios, dice que está inicializando un estático Pointer. Lo más probable es que haya encontrado el "fiasco de orden de inicialización estática": si dos objetos estáticos están en diferentes unidades de compilación, entonces no se define en qué orden se inicializaron. Entonces, si el constructor de uno depende de que el otro sea inicializado, entonces puede salirse con la suya, o puede que no. La ley de Sod dicta que el código funcionará durante la prueba y luego se romperá misteriosamente cuando se despliegue.

La mejor solución es evitar objetos estáticos; rara vez son una buena idea.

Otra posibilidad es la instanciación perezoso, algo como esto:

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

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

Esto puede tener problemas de su propio; Está garantizado que se construirá antes de ser utilizado, pero podría destruirse antes de que haya terminado con él, si un destructor estático accede a él, y puede haber problemas de seguridad de subprocesos. Para conocer los detalles sangrientos, consulte las numerosas discusiones sobre el patrón Singleton, que requiere una instancia estática. Los Singletons en C++ son un mundo de dolor, es mejor evitarlo si es posible.

+0

FWIW, es solo una buena variable global, no un singleton (no está impidiendo la creación de más 'RefCountMap''s). Sin embargo, creo que esta solución global es muy superior a un singleton. – GManNickG

+0

@GMan: tienes razón; He editado para mejorar la terminología. –

1

Es probable que haya dañado su pila en otro lugar de su programa. Ejecute su programa a través de un depurador de memoria (por ejemplo, valgrind) y descubra dónde está ocurriendo la corrupción.

+3

La respuesta de Mike es más probable ahora que dijiste que es un "Puntero" estático. Sin embargo, cuando no hay una inicialización estática involucrada, un bloqueo misterioso dentro de una clase o función de biblioteca estándar es casi siempre un problema de corrupción de montón. –

Cuestiones relacionadas