抛出异常会导致分段错误

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;
}

每当throw语句执行时,我都会遇到分段错误。 这是Valgrind输出的原因。 我不知道发生了什么事。

==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

我有几次迭代的单元测试正在进行中,但这里是当前与所有其他测试相同的错误:

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);*/
}

根据请求,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;
}

这是第一次Valgrind错误还是以前的?

我的猜测是,有以前的那些,其中一个是破坏内存并导致抛出。


戴夫,你的执行路径中缺少代码,这阻止了问题的解决:

  • DataMapReader构造函数;
  • 实现DataMapReader :: getDataMapFromFile();
  • DataMap构造函数;
  • CollectionFactory构造函数;
  • 我建议尽量剥离测试用例,而分段错误仍然可以重现。

    我对这个问题有以下猜测:

  • DataMapReader :: getDataMapFromFile()接受对std :: string的引用,然后将其存储在静态内存或DataMapReader实例或DataMap实例中。 这导致了未定义的行为,因为引用的std :: string对象将在退出DataMapReader :: getDataMapFromFile()后立即销毁,因此所有剩余的引用将自动失效。
  • DataMapReader :: getDataMapFromFile()返回对存储在堆栈中的DataMap实例的引用。 一旦DataMapReader :: getDataMapFromFile()返回并且调用dm的复制构造函数之前,这样的实例就会被销毁,这会导致未定义的行为。 这种情况不太可能,因为编译器通常会警告返回指向堆栈中存储的对象的指针或引用。
  • 如果DataMapReader :: getMapFromFile()按值返回DataMap,并且DataMap没有明确定义的拷贝构造函数和/或拷贝赋值操作符,或者它对那些不正确地处理拷贝指针和/或引用的构造函数和/ DataMap拥有的成员(或其他值存储的成员递归地具有相同的问题)。 在这种情况下,在DataMapReader :: getMapFromFile()返回之前,被引用的成员可以在DataMap析构函数中被销毁而被销毁,这会导致未定义的行为。
  • 虽然这与问题中提到的段错误无关,但在CollectionFactory :: createFromMap()中引发异常的代码中可能会出现相同的潜在问题:

  • 如果集合构造函数的生命周期小于Collection实例的生命周期,则不应存储对输入参数(std :: string和DataMap)的引用。
  • DataMap.initDataCollection()不应该存储指向Collection实例的指针,因为在堆栈上创建的Collection实例的生命周期小于DataMap实例的生命周期。 在从CollectionFactory :: createFromMap()返回之前,Collection实例将被销毁。
  • 集合应该已经正确实现了拷贝构造函数和/或拷贝赋值操作符,否则它将遭受上述问题的困扰。

  • 你如何链接代码? 如果您正在为实例创建共享库,则可能需要为位置无关的代码指定编译标志,例如-fPIC(gcc / g ++)。

    链接地址: http://www.djcxy.com/p/44799.html

    上一篇: throwing an exception causes segmentation fault

    下一篇: WPF Cursor on a partially transparent image