c++ - 在 C++ 中是否有任何方法导致整个堆栈帧展开? (除了使用异常(exception))

标签 c++ exception stack-unwinding

我一直在写一个延续——特别是协程——库。它类似于 std::thread(除了它是协作的)——每个执行上下文都在延续对象中表示。

问题是关于连续对象销毁。如果在执行上下文尚未正常退出时调用延续对象的 dtor,则应通过销毁对象的上下文强制关闭它。

这样,堆栈帧中的每个 C++ 对象都不会被正确销毁。这对任何人来说都不是一个愉快的情况 - 所以我决定找到一个解决方案。

起初,我想像下面这样使用异常来展开堆栈框架。 (请注意,下面只是有缺陷的伪代码。)

coroutine::~coroutine()
{
    status = FORCED_EXIT;
    switch_to(*this);
}

void coroutine::yield(coroutine& other_coroutine)
{
     // switch to other context, halt until invocation by other context
    switch_to(other_coroutine);

    if (status_ != FORCED_EXIT) {
        return; // resume
    } else {
        throw ContextClosingException;
    }
}

void coroutine::entrypoint()
{
    try {
        entry_function_();
    } catch(ContextClosingException& e) {
        switch_to(caller_coroutine);
    }
}

但是,我发现了一些严重的缺陷。任何如下“吞噬异常”的用户代码将完全打破协同调度的假设。

try {
    ...
} catch(...) { // ContextClosingException 
    // do nothing, just swallow exception.
}

所以我需要找到其他方法来调用堆栈展开(或任何其他方法来在延续中销毁堆栈对象)。符合标准的方式会很好——但是延续实现本身依赖于平台特定的 API,因此不可移植的方式是可以接受的。 (我使用的是 win32)

最佳答案

除异常外,C++ 标准中没有任何内容允许展开堆栈。协程(或对协程的支持)可能会在 C++11 之后提出(在 Going Native session 期间讨论过)。

您将不得不使用特定于操作系统的 C 调用(如果存在但我认为不存在),但很可能您只能靠自己使用 ASM。您可以查看 boost.context 库以获取示例解决方案。

关于c++ - 在 C++ 中是否有任何方法导致整个堆栈帧展开? (除了使用异常(exception)),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9286550/

相关文章:

c++ - 结构RUNTIME_FUNCTION

swift - 您如何有条件地修改 UINavigationController 的后退堆栈以跳过以前的条目,而不管您来自哪里?

c++ - 为什么 cppcheck 说 "Function parameter should be passed by reference"?

powershell - 尝试仅在终止异常时起作用吗?

c++ - std::string 构造函数抛出 std::out_of_range 异常

java - 异常处理和内存

c - 操纵 x64 展开信息以匹配 assembly Hook

c++ - 是否可以直接从队列成员函数访问一对成员变量?

c++ - 跨越二进制边界的异常

c++ - 有什么理由去寻找继承/多态性的替代方案吗?