2010-02-09 21 views
7
Collection CollectionFactory::createFromMap(const std::string& name, 
     const DataMap& dm) const 
{ 
    if (!Collection::isNameValid(name)) 
    { 
     const std::string error = "invalid collection name"; 
     throw std::invalid_argument(error); 
    } 
    Collection c(name, dm); 
    dm.initDataCollection(&c, true); 
    return c; 
} 

Cada vez que se ejecuta la instrucción throw, aparece un error de segmentación. Esta es la causa de la salida de Valgrind. No tengo idea de lo que está pasando.arrojando una excepción provoca un error de segmentación

==21124== Invalid read of size 1 
==21124== at 0x41D2190: parse_lsda_header(_Unwind_Context*, unsigned char const*, lsda_header_info*) (eh_personality.cc:62) 
==21124== by 0x41D24A9: __gxx_personality_v0 (eh_personality.cc:228) 
==21124== by 0x4200220: _Unwind_RaiseException (unwind.inc:109) 
==21124== by 0x41D2C9C: __cxa_throw (eh_throw.cc:75) 
==21124== by 0x4079BFB: corestore::CollectionFactory::createFromMap(std::string const&, corestore::DataMap const&) const (CollectionFactory.C:43) 
==21124== by 0x8188F86: CollectionFactoryTest::testCreateNewFromMap_InvalidName() (CollectionFactoryTest.C:91) 
==21124== by 0x81895D3: CppUnit::TestCaller<CollectionFactoryTest>::runTest() (TestCaller.h:166) 
==21124== by 0x40D1BB5: CppUnit::TestCaseMethodFunctor::operator()() const (TestCase.cpp:34) 
==21124== by 0x40C18E3: CppUnit::DefaultProtector::protect(CppUnit::Functor const&, CppUnit::ProtectorContext const&) (DefaultProtector.cpp:15) 
==21124== by 0x40CD0FC: CppUnit::ProtectorChain::ProtectFunctor::operator()() const (ProtectorChain.cpp:20) 
==21124== by 0x40CCA65: CppUnit::ProtectorChain::protect(CppUnit::Functor const&, CppUnit::ProtectorContext const&) (ProtectorChain.cpp:77) 
==21124== by 0x40DC6C4: CppUnit::TestResult::protect(CppUnit::Functor const&, CppUnit::Test*, std::string const&) (TestResult.cpp:178) 
==21124== Address 0xc82f is not stack'd, malloc'd or (recently) free'd 

He tenido varias iteraciones de la prueba de la unidad que es el bombardeo, pero aquí es la actual que presenta el mismo error como todos los demás:

void CollectionFactoryTest::testCreateNewFromMap_InvalidName() 
{ 
    const char* MAP_FILE = 
      "smallMapWithThreeSets.xml"; 
    const char* NAME1 = "name/invalidname"; 
    const char* NAME2 = "name/invalidname"; 

    DataMapReader dmr; 
    DataMap dm = dmr.getDataMapFromFile(MAP_FILE); 

    CollectionFactory cf; 
    try 
    { 
     cf.createFromMap(NAME1, dm); 
    } 
    catch (std::exception const& e) 
    { 
     std::cerr << e.what() << std::endl; 
    } 

    /*CPPUNIT_ASSERT_THROW(cf.createFromMap(NAME1, dm), std::invalid_argument); 
    CPPUNIT_ASSERT_THROW(cf.createFromMap(NAME2, dm), std::invalid_argument);*/ 
} 

Por la petición, el contenido de isNameValid :

bool Collection::isNameValid(const std::string& name) 
{ 
    /* can't be blank */ 
    if(name.length() == 0) 
    { 
     return false; 
    } 
    /* Can't contain '/' */ 
    if(name.find('/') != std::string::npos) 
    { 
     return false; 
    } 
    return true; 
} 

Respuesta

1

¿Es ese el primer error de Valgrind o hay otros anteriores?

Supongo que hay otras anteriores y una de ellas es corromper la memoria y hacer que throw se rompa.

+0

Todos los errores anteriores involucran valores no inicializados en llamadas al sistema (sigaction, write) o salto condicional en valores no inicializados, por lo que no están dañando la memoria. – Dave

+0

¿Se puede reducir el problema? Si solo ejecuta testCreateNewFromMap_InvalidName ¿todavía obtiene el segfault? –

+0

Creé un programa separado. Es solo principal. Todo lo que hace es lo que estaba en esa prueba. Se produce el mismo error de segmentación. También creé un programa separado que arroja una excepción (no usa mi biblioteca), y funciona. Además, si no atrapo, obtengo una salida limpia con una impresión de "Cancelado". – Dave

1

¿Cómo enlaza el código? Si está creando una biblioteca compartida, por ejemplo, es posible que necesite especificar indicadores de compilación para el código independiente de la posición, como -fPIC (gcc/g ++).

+0

Las excepciones se lanzan dentro de una biblioteca compartida. De hecho, cuando me conecto estáticamente, el error desaparece. Sin embargo, en el trabajo, tenemos dos configuraciones de sistema operativo. El sistema más nuevo de 64 bits usa el Compilador Intel 11.1 en lugar del antiguo 9.1. También usa gcc4 + en lugar de 3.3, y está trabajando en el sistema más nuevo. Estoy esperando trabajar con Intel para ver si este es un problema conocido con el compilador 9.1. – Dave

2

de Dave, hay falta de código en su ruta de ejecución, lo que impide clavar el problema:

  • DataMapReader constructor;
  • implementación de DataMapReader :: getDataMapFromFile();
  • Constructor de mapa de datos;
  • CollectionFactory constructor;

Recomendaría intentar desmantelar el caso de prueba tanto como sea posible mientras la falla de segmentación todavía se pueda reproducir.

que tienen las siguientes conjeturas para el problema:

  • DataMapReader :: getDataMapFromFile() acepta una referencia a std :: string y luego lo almacena en la memoria, ya sea estática o en DataMapReader instancia o en caso DataMap. Esto conduce a un comportamiento indefinido, porque el objeto std :: string referenciado se destruirá inmediatamente después de salir de DataMapReader :: getDataMapFromFile(), por lo que todas las referencias restantes se vuelven automáticamente no válidas.
  • DataMapReader :: getDataMapFromFile() devuelve una referencia a la instancia de DataMap almacenada en una pila. Tal instancia se destruirá tan pronto como DataMapReader :: getDataMapFromFile() regrese y antes de que se invoque el constructor de copias para dm, lo que conduce a un comportamiento indefinido. Este caso es poco probable, porque los compiladores generalmente advierten sobre la devolución de punteros o referencias a objetos almacenados en una pila.
  • If DataMapReader :: getMapFromFile() devuelve DataMap por valor y DataMap no tiene un operador de asignación de copiado y/o copiado explícitamente definido, o tiene implementaciones incorrectas para el constructor y/u operador, que maneja incorrectamente la copia de punteros y/o las referencias a los miembros propiedad de DataMap (u otros miembros almacenados por valor tienen el mismo problema recursivamente). En este caso, los miembros a los que se hace referencia pueden destruirse en el destructor de DataMap llamado para la instancia almacenada en una pila antes de regresar de DataMapReader :: getMapFromFile(), lo que conduce a un comportamiento indefinido.

Aunque esto no está relacionado con el fallo de segmentación mencionada en la pregunta, los mismos problemas potenciales pueden aplicar al código de abajo lanzar una excepción en el CollectionFactory :: createFromMap(): constructor de

  • Colección no debe almacenar referencias a los parámetros de entrada (std :: string y DataMap) si su vida útil es menor que la duración de la instancia de la Colección.
  • DataMap.initDataCollection() no debe almacenar el puntero a la instancia de Colección, porque la duración de la instancia de Colección creada en una pila es menor que la duración de la instancia de DataMap. La instancia de la colección se destruirá antes de volver de CollectionFactory :: createFromMap().
  • La colección debe tener un constructor de copias y/o un operador de asignación de copias debidamente implementados, de lo contrario sufrirá el problema descrito anteriormente.
Cuestiones relacionadas