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

How do I try/catch an object creation in C++?

本文关键字:对象 创建 C++      更新时间:2023-10-16

我在catchsegov中运行我的程序,它显示boost::archive::text_oarchive析构函数在我的程序segfault之前运行:

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析构函数运行的原因和我的代码分段。。。帮助

您可以创建一个指向outarchive的指针,并在try块中对其进行初始化(只是为了了解异常的原因。如果您需要在了解异常原因后继续使用指针,请将其分配给实际生产代码中的智能指针。如果您想这样做,请参阅例如std::aut_ptr或std::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 );
}

这一行没有意义:

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

不可能为以下行调用text_oarchive析构函数:

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

因此,你很可能被你正在使用的工具愚弄了,默认情况下,该工具链接到此行,而没有任何其他行链接到。发生这种情况是因为析构函数是隐式的,因此没有任何源代码行可以引用

顺便说一句,您可以用c++filt管道传输工具的输出,以获得C++解映射名称(更容易阅读),如下所示:

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

事实上,如果你有分段错误,这意味着在你的代码中的某个地方,内存访问是出乎意料的(比如写入空指针或超出分配的区域,等等…)

当你发现错误时,要么为时已晚,要么没有。

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

当处理空指针(读取/写入/访问)时,通常不会太晚,会立即发送分段故障信号(SIGSEGV)。

在前一种情况下,您可以使用Valgrind,它会告诉您何时完成了越界访问。

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

还请注意,分割错误不会被try/catch块捕获,因此尝试这样做没有意义,它不会起作用。