_Unwind_SjLj_Unregister 和 _Unwind_SjLj_Register 是啥?
Posted
技术标签:
【中文标题】_Unwind_SjLj_Unregister 和 _Unwind_SjLj_Register 是啥?【英文标题】:What are _Unwind_SjLj_Unregister and _Unwind_SjLj_Register?_Unwind_SjLj_Unregister 和 _Unwind_SjLj_Register 是什么? 【发布时间】:2011-06-29 05:10:09 【问题描述】:什么是_Unwind_SjLj_Unregister 和_Unwind_SjLj_Register?在我的 gprof 报告中,我将他们列为我的***处理器时间用户。谷歌只返回链接给抱怨这两个错误的人。
这是我的报告中唯一有时间的部分!= 0:
Flat profile:
Each sample counts as 0.01 seconds.
% cumulative self self total
time seconds seconds calls ms/call ms/call name
33.33 0.03 0.03 _Unwind_SjLj_Unregister
22.22 0.05 0.02 _Unwind_SjLj_Register
11.11 0.06 0.01 13886 0.00 0.00 toint(std::string, int)
11.11 0.07 0.01 4380 0.00 0.00 hexlify(std::string)
11.11 0.08 0.01 2994 0.00 0.00 std::_Deque_iterator<unsigned char, unsigned char const&, unsigned char const*>::operator+(int) const
11.11 0.09 0.01 std::string::assign(char const*, unsigned int)
我正在运行 Windows 7 x64,并使用代码块 10.05 gcc 进行编译
编辑:
在启用强制程序运行 64 秒的功能后,它现在看起来像:
Flat profile:
Each sample counts as 0.01 seconds.
% cumulative self self total
time seconds seconds calls s/call s/call name
8.45 3.49 3.49 _Unwind_SjLj_Register
7.36 6.53 3.04 4000006 0.00 0.00 CAST128::setkey(std::string)
5.86 8.95 2.42 _Unwind_SjLj_Unregister
4.36 10.75 1.80 64000080 0.00 0.00 CAST128::F(int&, unsigned int&, unsigned int&, unsigned char&)
3.68 12.27 1.52 __dynamic_cast
3.37 13.66 1.39 std::string::_Rep::_S_create(unsigned int, unsigned int, std::allocator<char> const&)
3.25 15.00 1.34 std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string()
2.88 16.19 1.19 std::istreambuf_iterator<char, std::char_traits<char> > std::num_get<char, std::istreambuf_iterator<char, std::char_traits<char> > >::_M_extract_int<unsigned long long>(std::istreambuf_iterator<char, std::char_traits<char> >, std::istreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, std::_Ios_Iostate&, unsigned long long&) const
【问题讨论】:
【参考方案1】:我相信这是异常处理。当人们试图链接到在不同编译器中构建的 C++ 库时,问题大多会出现。
【讨论】:
这是在上面是好事还是坏事?我没有遇到任何问题(我认为)。它就在报告中 嗯。您的程序将 55% 的时间用于异常处理程序,这有点令人惊讶。但让我们更合乎逻辑地思考一下:我注意到您的个人资料准确测量了 0.03 秒和 0.02 秒。其他所有时间为 0.01 秒。看起来程序几乎不需要任何时间来运行,并且分析器无法在小于 0.01 秒的粒度内测量任何东西。您需要更长的时间才能获得任何有意义的信息。您基本上是在看着六粒沙子,其中两粒比其他沙粒大一点,并试图弄清楚如何清理海滩。 哈哈。我的程序运行大约需要 0.2 秒。这可以解释它 我将我的程序改为运行 64 秒,两个异常处理程序仍在顶部。 CAST128 现在位居榜首,因为它运行了 100000 多次 嗯。我用MinGW编译了一个代码,每次我的LastError都被改变了,所以我很困惑。我在反汇编中发现罪魁祸首是_Unwind_SjLj_Register
,当然,它是由编译器插入的,而不是我。我想知道,这是否应该被视为 MinGW 的错误?【参考方案2】:
我无法在这里给出最佳答案,但我知道 SjLj 指的是 setjmp 和 longjmp。这些通常用于异常处理。我认为_Unwind_SjLj_Register
将在您输入try
语句(以“注册” SjLj 异常处理程序)时由编译器在内部使用,而_Unwind_SjLj_Unregister
将在您退出try
语句时使用。不过有点猜测。
【讨论】:
我不相信我的程序中有任何try
s。**编辑**不。我检查了。它可能隐藏在某些 stl 库中
也许您正在调用的某个库中进行了尝试。
但是你使用的是 C++ 标准库,它有try
s。
当你进入 try
块时它们不会被调用,但是当你创建/销毁带有析构函数的本地对象时,如果抛出异常则需要调用它们。
@Mike Seymour,很高兴知道。这可能解释了 calccrypto 看到它们的原因,即使他没有直接使用 try/catch。【参考方案3】:
首先:对于这样的问题,可能值得一提的是您的编译器和平台。
现在:在某些平台/某些配置/某些编译器上,C++ 中的异常处理是使用“setjmp”和“longjmp”函数(标准 C 库的一部分)实现的。 _Unwind_SjLj_[Un]register 方法与此有关。粗略地说,当进入 try..catch 块时,需要注册处理程序,离开块时,需要注销处理程序。
【讨论】:
【参考方案4】:这是一个非常具体的案例,但是我在 R 中使用 Rcpp 包时遇到了这个错误。结果是 -std=c++11 标志导致了这个问题,并且使用 -std=c++0x 一切正常.
【讨论】:
【参考方案5】:根据我在 Windows 上使用 gcc 的经验,您可以通过避免内存分配或在内部循环中分配内存的可能性来避免大量此类开销。其他答案指出,当可能引发异常并导致调用析构函数时,您会收到这些调用。在我的程序中,大多数地方可能抛出的异常是 std::bad_alloc ,当内存分配失败时会出现这种异常。
因此,如果您的程序中的潜在异常也主要是 std::bad_alloc,并且您可以将分配或潜在分配移出内部循环,那么 GCC 将不必处理潜在的清理内部循环中的 std::bad_alloc 异常。那应该加快速度。记住要考虑像 vector::push_back 这样的东西可以分配内存。即使您首先调用 vector::reserve 以排除重新分配,GCC 也可能不够聪明,无法意识到不会发生重新分配。
我不知道您使用的是什么版本的 GCC,但我相信最新版本的 GCC 使用了没有这种开销的异常处理机制。不过,我可能是错的。当然可以实现不需要动态注册析构函数的异常处理机制,因为可以从程序计数器中推断出需要调用的析构函数。
【讨论】:
以上是关于_Unwind_SjLj_Unregister 和 _Unwind_SjLj_Register 是啥?的主要内容,如果未能解决你的问题,请参考以下文章
\_\_setitem\_\_和\_\_getitem和\_\_delitem__
__setattr__和__delattr__和__getattr__
描述符(\_\_get\_\_和\_\_set\_\_和\_\_delete\_\_)