栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

C++:异常处理:栈展开

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C++:异常处理:栈展开

文章目录
  • 模板库最为被人称道的是:晦涩难懂,都不如直接看汇编。
  • stack unwinding
  • 怎么理解
  • 合理的翻译
  • 汇编

模板库最为被人称道的是:晦涩难懂,都不如直接看汇编。

有没有什么技巧,可以让人,快速上手。
这样一层嵌套着一层,不是办法呀。

stack unwinding 怎么理解

https://blog.csdn.net/shltsh/article/details/46039365
https://www.geeksforgeeks.org/stack-unwinding-in-c/

从上面这个文章看,展开的意思是异常处理程序,会对调用栈上的所有函数,搜索是否有对应的异常处理,如果有就进入相应的处理函数,如果没有直接从栈上将该函数pop出去。在pop出去之前,会调用局部对象的析构函数。但是堆上分配的对象,会出现问题。

字面理解不应该翻译成展开,因为栈本来就在那里,不需再要展开。
只是需要去根据栈的结构去一层一层的做搜索异常处理。弹出操作。

合理的翻译

栈内异常搜索

汇编
#include 
using namespace std;
  
// A sample function f1() that throws an int exception
void f1() throw(int)
{
    cout << "n f1() Start ";
    throw 100;
    cout << "n f1() End ";
}
  
// Another sample function f2() that calls f1()
void f2() throw(int)
{
    cout << "n f2() Start ";
    f1();
    cout << "n f2() End ";
}
  
// Another sample function f3() that calls f2() and handles
// exception thrown by f1()
void f3()
{
    cout << "n f3() Start ";
    try {
        f2();
    }
    catch (int i) {
        cout << "n Caught Exception: " << i;
    }
    cout << "n f3() End";
}
  
// Driver Code
int main()
{
    f3();
  
    getchar();
    return 0;
}

先看抛出异常的f1 函数

0000000000400ac6 :
  400ac6:       55                      push   %rbp
  400ac7:       48 89 e5                mov    %rsp,%rbp
  400aca:       be f2 0c 40 00          mov    $0x400cf2,%esi
  400acf:       bf a0 20 60 00          mov    $0x6020a0,%edi
  400ad4:       e8 67 fe ff ff          callq  400940  >& std::operator<<  >(s
td::basic_ostream >&, char const*)@plt>
  400ad9:       bf 04 00 00 00          mov    $0x4,%edi   传进去一个 4,调用 __cxa_allocate_exception 函数
  400ade:       e8 3d fe ff ff          callq  400920 <__cxa_allocate_exception@plt>
  400ae3:       c7 00 64 00 00 00       movl   $0x64,(%rax)   、、 这里返回的是一个地址,向地址存内存放 0x64 == 100
  400ae9:       ba 00 00 00 00          mov    $0x0,%edx
  400aee:       be d0 1d 60 00          mov    $0x601dd0,%esi
  400af3:       48 89 c7                mov    %rax,%rdi
  400af6:       e8 a5 fe ff ff          callq  4009a0 <__cxa_throw@plt>
  400afb:       48 83 fa ff             cmp    $0xffffffffffffffff,%rdx
  400aff:       74 08                   je     400b09 
  400b01:       48 89 c7                mov    %rax,%rdi
  400b04:       e8 b7 fe ff ff          callq  4009c0 <_Unwind_Resume@plt>
  400b09:       48 89 c7                mov    %rax,%rdi
  400b0c:       e8 3f fe ff ff          callq  400950 <__cxa_call_unexpected@plt>

0000000000400920 <__cxa_allocate_exception@plt>:
  400920:       ff 25 fa 16 20 00       jmpq   *0x2016fa(%rip)        # 602020 <__cxa_allocate_exception@CXXABI_1.3> 直接跳转到 这个函数,CXXABI_1.3 接口函数,库里的函数。libstdc++ 库里
  400926:       68 01 00 00 00          pushq  $0x1
  40092b:       e9 d0 ff ff ff          jmpq   400900 <.plt>

/libstdc+±v3/libsupc++/eh_alloc.cc

struct __cxa_refcounted_exception
{
  // Manage this header.
  _Atomic_word referenceCount;
  // __cxa_exception must be last, and no padding can be after it.
  __cxa_exception exc;
};
extern "C" void *
是一个C格式函数名。C格式编译。
__cxxabiv1::__cxa_allocate_exception(std::size_t thrown_size) _GLIBCXX_NOTHROW
{
  void *ret;

  thrown_size += sizeof (__cxa_refcounted_exception);  、、 传进来的大小加上__cxa_refcounted_exception 这个结构体的大小
  ret = malloc (thrown_size);  、、 申请内存

  if (!ret)
    ret = emergency_pool.allocate (thrown_size);   如果申请成功,就会调用emergency_pool的allocate;malloc申请的内存,怎么使用?

  if (!ret)
    std::terminate ();   、、、 如果没有申请到,terminate;

  memset (ret, 0, sizeof (__cxa_refcounted_exception));

  return (void *)((char *)ret + sizeof (__cxa_refcounted_exception));
}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/604831.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号