Quu*_*one 7 c++ exception language-lawyer
我对所有三个主流编译器/运行时对此 C++ 代码( Godbolt)的处理感到困惑:
\nint main() {\n int i = 42;\n try {\n throw &i;\n } catch (void*&) {\n puts("incorrectly hit?");\n } catch (...) {}\n try {\n throw nullptr;\n } catch (void*&) {\n puts("incorrectly hit?");\n } catch (...) {}\n}\nRun Code Online (Sandbox Code Playgroud)\n请注意,此处抛出的“异常对象”是 resp 类型的对象int*。std::nullptr_t。但被捕获的对象是类型void*。唯一可行的方法是运行时创建一个void*从异常对象类型转换而来的临时对象,对吧?那么void*&catch 处理程序中的 必须引用临时对象,而不是实际的运行中异常对象?
仔细看看措辞,[ except.handle ]说:
\n\n\n处理程序与类型为
\nEif的异常对象匹配\n
\n- 处理程序的类型为
\ncv Tor ,cv T&并且E和T是相同类型(忽略顶级 cv 限定符),或者- 处理程序的类型为
\ncv Torcv T&且是, orT的明确公共基类E- 处理程序的类型为
\ncv Torconst T&其中T是指针或指向成员的指针类型,并且是可以通过 [...] 标准指针转换 [...]E转换为的指针或指向成员的指针类型,或者T- 处理程序的类型为
\ncv T或const T&其中T是指针或指向成员的指针类型,并且E是std\xe2\x80\x8b::\xe2\x80\x8bnullptr_t。
这些要点似乎都不适用。那么,这三个供应商允许这个处理程序受到攻击的行为难道就是错误的吗?catch[except.handle] 措辞并不是新的;它最近在 2016 年被触及(CWG2093 ),但似乎是在 2012 年左右作为CWG388和CWG729的结果而引入的。
388 号决议称“该决议需要更改 ABI”;这是否意味着所有三个供应商根本就懒得去实施它?
\n(更新为添加:[except.handle]/15说:“当处理程序声明对对象的引用时,对引用对象的任何更改都是对异常对象的更改,并且如果该对象被重新抛出,则会生效”\xe2\ x80\x94 但当引用绑定到转换后的临时变量时,这显然是不正确的。我认为可以通过在“引用”之前添加形容词“非常量”来挽救该句子。)
\n