[Cpp基础][11]"异常"

异常

  • C++内所说的异常是指:可以预见的非正常状况,例如输入的指针为空;而非不可预见的问题,例如突然停电,或者突然被用户把进程kill掉,并不是C++需要处理的"异常"
  • 异常特性会导致程序的执行流程不可控,且往往对OS及runtime有一定的要求(可移植性差),所以没有特殊需求时,不应当使用这个特性.
  • throw-try-catch是异常系统的典型三个环节.
    • throw出的可以是任意对象,只要catch处声明的对象可以用throw的对象初始化即可.习惯上我们会专门设计一个类,因为自定义类可以承载更多的信息
    • 异常catch中的形参可以使用引用,以使用多态机制
  • 异常抛出后寻找catch的过程称为栈展开,被展开的函数栈内所有局部对象都将被销毁,因此抛出的异常对象必须不依赖局部对象.
  • 标准库内提供了以exception为基类的若干异常,我们可以使用这个类,也可以自定义类,该类的const char * what()成员用于给用户提供信息.
    • catch时,优先使用引用, 从而保证能派生类实例能绑定到基类参数上.
  • 构造函数内可以throw异常;析构函数若抛出异常,则会直接ternimate.
  • catch的匹配顺序是确定的,第一个能初始化的catch将用于匹配,而非最优的那个.
    • 匹配过程中仅允许非const到const,数组到指针,派生类到基类这种转换.
  • 处理异常时,可以处理一半再然后通过throw再次将其抛给上层.
  • 一般而言,对于一个函数,当它碰到非正常状况时(例如空指针,或者内部函数抛出异常),其异常安全性要求有三个层次:
    • 低:该函数将异常抛出,该函数的输入对象都可以正常析构,不存在内存泄漏.
    • 中:该函数将异常抛出,且恢复相关对象到调用该函数前的原状,仿佛什么都没发生过.
    • 高:该函数保证不会抛出异常,换言之,该函数能自己处理所有可能的错误,从而保证总是能正常return.(当然,正常return不意味着结果和你预期相同, 例如,可以return一个错误码给调用者)
  • 健壮的,不抛出异常的swap()是高等级异常安全的重要工具.这样就可以使用copy-修改-swap的流程来保证异常安全.
  • noexcept
    • 可以用于标记函数是否抛出异常
    • noexcept的函数和普通函数是不同的,需要使用不同的函数指针.
    • 编译器一般提供了trait,可以在编译期求值,判断一个函数是否抛出异常
    • 对于std::vector<MyType>等场合,仅当MyType的移动构造/移动拷贝为noexcept时,vector整体才能支持移动,否则将会默认使用拷贝.

Read more

Coroutine

从一般概念上说, 协程是特殊的函数调用: 被调用的函数可以在可控的位置被中断,然后在下一次调用时,继续从上次中断的位置继续执行。 本文主要通过Python的协程来介绍协程, 这是我唯一熟悉的一种协程实现. Classic Coroutine 下面的python代码很好的说明了协程的核心功能 def co_routine(): recv0 = yield 996 # hangs here after first coro.send assert recv0 == "Second" yield 711 # hangs here after second coro.send return def main(): coro = co_routine() # Create a new coroutine object value = coro.send(None)

By Edimetia3D

GDB with Python

这篇文章的主要应用场景是调试Python的C/C++ Extension 1. 同时使用pdb / gdb 进行调试. 通俗点说, 既可以break在 .py 文件中,也可以break在 .cc 文件中 2. 在gdb中不但可以获得常规的调试信息, 还可以获得python VM 的调试信息, 例如获得python的调用栈, 访问Python局部变量等. 这将会在调试exception时(如Segmentfalut)非常有用, 这种场景下, 定位 Python VM 正运行到哪一行代码往往可以提供一些直观的重要信息. 第一步: 编译源码以获得一些辅助数据. 我们并不真的需要使用从源码编译的Python, 但是一些调试相关的辅助文件需要从源码中获得, 包括 python-gdb.py及debug symbol等. 在 https://www.python.org/ftp/python/ 或 https://github.com/python/cpython

By Edimetia3D

Bazel Notes

这是一篇2019年左右的记录, 内容可能过时, 也不太全面 杂谈 Bazel是Google为Monorepo服务而开发的构建工具. 首先是巨大,当问题的规模变大,事情总是会变得更复杂. 而Google面对的"巨大Monorepo",应该是世间罕有的. 然后是Monorepo,这极大的影响了代码的组织风格.例如,你要写一个操作系统内核ProjectOS,还要写一个游戏ProjectGame.在传统的开发习惯中,这两个项目会组织到两个不同的Repo里,PorjectOS和ProjectGame之间无法直接相互引用,例如,你在ProjectOS里写了一个高级的数据结构,想要在Game里也使用,要么直接复制粘贴,要么是创建一个新的CommonRepo,把可公用的代码都放在Common里,然后两个项目各自引入Common作为依赖. 使用MonoRepo则不存在这个问题,Game可以直接依赖OS内的组件,按照Bazel的语法描述,就是在Game中可以直接使用@ProjectOS//path/to/package:AdvancedStruct.当然,你仍然可以选择重构一

By Edimetia3D

Unix related things

这是一篇2017年左右的记录, 仅用作分享 杂 * 在shell内能干的事,我们都可以比较简单地通过系统调用实现. * `称为反引号,^称为脱字符,常用来表示CTRL * windows的系统调用是不开放的,windows下只能直接使用windows.h里的windows API. * /dev目录下的设备是供用于程序直接使用的,主要由block,char,pipe,socket类型 * 并不是所有设备都能映射为这种形式 * /sys/device/目录称为sysfs,他下面存放了所有设备的信息.(不能直接从/dev获得任何设备信息) * udevadm info --query=all --name="/dev/sda1"可以用于查询/dev下某个设备对应的sysfs路径 权限系统 * 权限系统由两部分组成 * 文件属性:用于标注文件owner,所属组,以及权限的设定(默认只有owner和root可以修改权限设置) *

By Edimetia3D