如何在C ++中尝试/捕获对象创建?

时间:2015-11-27 10:47:32

标签: c++ c++11 boost constructor destructor

我在catchsegv中运行我的程序,它显示在我的程序段错误之前运行的boost::archive::text_oarchive析构函数:

Backtrace:
??:?(_ZN5boost7archive28basic_streambuf_locale_saverIcSt11char_traitsIcEED1Ev)[0x50c678]
??:?(_ZN5boost7archive21basic_text_oprimitiveISoED1Ev)[0x50c833]
/usr/local/include/boost/archive/text_oarchive.hpp:97(_ZN5boost7archive18text_oarchive_implINS0_13text_oarchiveEED2Ev)[0x417baf]
/usr/local/include/boost/archive/text_oarchive.hpp:114(_ZN5boost7archive13text_oarchiveD2Ev)[0x416645]
...

我不确定为什么boost::archive::text_oarchive析构函数正在运行,据我所知,该对象尚未完成。所以我的猜测是抛出异常,这就是析构函数运行的原因..?

我有这段代码:

std::stringstream ss;
boost::archive::text_oarchive outArchive(ss);
outArchive << *instPtr;

catchsegv输出显示在中间线上调用了text_oarchive析构函数,我的程序从未到达第三行。

所以我想做的是将outArchive构造包装在try / catch块中。我试过这样:

boost::archive::text_oarchive outArchive;
try {
  boost::archive::text_oarchive outArchiveTemp(ss);
  outArchive = outArchiveTemp;
}
catch ( std::exception& ex ) {
  BOOST_LOG_TRIVIAL(info) << "Error creating text_oarchive...";
  exit( 1 );
}

但这并不起作用,因为第一行没有outArchive的默认构造函数。我害怕我不能很好地理解C ++做我想做的事情,基本上是尝试/捕获对象来诊断outArchive析构函数运行的原因和我的代码segfaulting ...帮忙?

2 个答案:

答案 0 :(得分:1)

您可以创建一个指向outarchive的指针,然后在try块中初始化它(只是为了理解异常的原因。如果需要保留,请将其分配给实际生产代码中的智能指针即使您已了解异常原因,也请使用指针。例如,如果您想这样做,请参阅std::aut_ptrstd::unique_ptr

boost::archive::text_oarchive *outArchive;
try {
  outArchive = new boost::archive::text_oarchive(ss);
}
catch ( std::exception& ex ) {
  BOOST_LOG_TRIVIAL(error) << "Error creating text_oarchive..."<<ex;
  exit( 1 );
}

答案 1 :(得分:1)

这条线没有意义:

  

catchsegv输出显示在中间行调用text_oarchive析构函数,我的程序永远不会到达第三行。

为此行调用text_oarchive析构函数是不可能的:

boost::archive::text_oarchive outArchive(ss);

因此,您可能会被正在使用的工具所迷惑,该工具默认链接到此行没有任何其他行链接到。 这是因为析构函数是隐式的,因此没有任何源代码行可供引用。

作为旁注,您可以使用c++filt管道工具的输出以获取C ++解码名称(更容易阅读),如下所示:

catchsigv [your args here] 2>&1 | c++filt

实际上,如果你有一个分段错误,那就意味着代码中的某个地方,内存访问是意外完成的(比如写入空指针或者超出分配区域等等)< / p>

当你发现错误时,要么已经太晚了,要不是。

例如,对于越界访问,通常为时已晚,错误可能由分配器(new / delete / malloc / free / etc)发现下次调用分配器。

当处理空指针(读/写/访问)时,它的通常不会太晚,立即发送分段错误信号(SIGSEGV)。 / p>

在前一种情况下,您可以使用Valgrind在您完成超出限制访问时告诉您。

在后一种情况下,您应该在调试器(gdb / lldb / etc ...)下运行程序,调试器将停在信号引发的确切位置。检查周围的局部变量(和this)是否使用了空值。

另请注意,try / catch块阻止了分段错误 ,因此没有必要尝试这样做,它是&#39;不会工作。