首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >抛出异常导致分段错误

抛出异常导致分段错误
EN

Stack Overflow用户
提问于 2010-02-10 03:31:50
回答 3查看 4.3K关注 0票数 7
代码语言:javascript
代码运行次数:0
运行
复制
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输出的原因。我不知道发生了什么。

代码语言:javascript
代码运行次数:0
运行
复制
==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

我已经有过几次单元测试的迭代,但这里是当前的一个,它显示了与所有其他单元测试相同的bug:

代码语言:javascript
代码运行次数:0
运行
复制
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的内容:

代码语言:javascript
代码运行次数:0
运行
复制
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;
}
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2010-02-10 03:35:52

这是第一个Valgrind错误,还是之前的错误?

我的猜测是,有以前的问题,其中之一是破坏内存并导致抛出中断。

票数 2
EN

Stack Overflow用户

发布于 2010-02-17 13:28:06

Dave,在你的执行路径中有缺失的代码,这阻止了问题的解决:

constructor;

  • implementation of DataMapReader::getDataMapFromFile();

  • DataMap constructor;

  • CollectionFactory
  • DataMapReader
    • DataMapReader

我建议在分段错误仍然可重现的情况下尽可能地剥离测试用例。

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

  • DataMapReader::getDataMapFromFile()接受对std::string的引用,然后将其存储在静态内存、DataMapReader实例或DataMap实例中。这会导致未定义的行为,因为引用的std::string对象将在退出DataMapReader::getDataMapFromFile()后立即销毁,因此所有剩余的引用将自动变为invalid.
  • DataMapReader::getDataMapFromFile()返回对堆栈上存储的DataMap实例的引用。一旦DataMapReader::getDataMapFromFile()返回,就会在调用dm的复制构造函数之前销毁这样的实例,这会导致未定义的行为。这种情况不太可能发生,因为编译器通常会警告返回指向堆栈上存储的对象的指针或引用。
  • If DataMapReader::getMapFromFile()按值返回DataMap,而DataMap没有显式定义的复制构造函数和/或复制赋值运算符,或者它对这些构造函数和/或运算符的实现不正确,这些实现不正确地处理对DataMap拥有的成员的指针和/或引用的复制(或通过值存储的其他成员以递归方式具有相同的问题)。在这种情况下,在从DataMapReader::getMapFromFile()返回之前,可以在为存储在堆栈上的实例调用的DataMap析构函数中销毁引用的成员,这会导致未定义的行为。

虽然这与问题中提到的分段错误无关,但同样的潜在问题也可能适用于下面在CollectionFactory::createFromMap()中抛出异常的代码:

如果输入参数(std::string和DataMap)的生存期小于集合实例的生存期,则

  • 集合构造函数不应存储对这些参数的引用,因为在堆栈上创建的集合实例的生存期小于DataMap实例的生存期。集合实例在从CollectionFactory::createFromMap().
  • Collection返回之前将被销毁应正确实现复制构造函数和/或复制赋值运算符,否则它将遇到上述问题。
票数 2
EN

Stack Overflow用户

发布于 2010-02-15 01:39:26

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

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2231899

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档