C++;以及一种跳出动态生成代码的安全方法 我的项目是用C++编写的,它利用动态生成的代码把一些东西粘在一起(使用法布里斯·贝拉的TCC和一点手工生成的汇编thunk)。动态生成的代码有时会跳进C++和Real.中实现的“运行时助手”。 有一个特性,它可以完全放弃动态生成的代码,无论它在哪里,跳回C++(调用方)。为了实现这一点,我只是使用C++异常:运行时助手(冒充C函数)只会抛出C++异常,并通过生成的函数传播回C++。我使用的是SJLJ,到目前为止一切正常,但我不想依赖于特定的实现(我读到只有SJLJ才安全) 除上述中止方案外,我的C++代码主要使用异常情况下的异常,它不用于通用控制流。然而,我依靠RAII自动销毁堆栈上的对象 >强>我的问题是:在使用LojJMP/SETJMP时是理论上和实际上的安全,在调用动态生成函数之前提供SETJMP,并且提供LoJMP从不通过依赖RAII的C++函数传播(我必须确保C++中没有运行时助手使用它)并且总是在setjmp中着陆(设置在函数之前) 或C++是如此脆弱,即使这样也不能保证工作正常,会破坏某些东西吗?或者,如果抛出实际异常,C++可能会中断吗?如果异常在本地抛出并立即捕获(在生成的程序集调用的运行时帮助程序中),那么它安全吗?或者仅仅因为有一些外来的框架,它就会拒绝工作

C++;以及一种跳出动态生成代码的安全方法 我的项目是用C++编写的,它利用动态生成的代码把一些东西粘在一起(使用法布里斯·贝拉的TCC和一点手工生成的汇编thunk)。动态生成的代码有时会跳进C++和Real.中实现的“运行时助手”。 有一个特性,它可以完全放弃动态生成的代码,无论它在哪里,跳回C++(调用方)。为了实现这一点,我只是使用C++异常:运行时助手(冒充C函数)只会抛出C++异常,并通过生成的函数传播回C++。我使用的是SJLJ,到目前为止一切正常,但我不想依赖于特定的实现(我读到只有SJLJ才安全) 除上述中止方案外,我的C++代码主要使用异常情况下的异常,它不用于通用控制流。然而,我依靠RAII自动销毁堆栈上的对象 >强>我的问题是:在使用LojJMP/SETJMP时是理论上和实际上的安全,在调用动态生成函数之前提供SETJMP,并且提供LoJMP从不通过依赖RAII的C++函数传播(我必须确保C++中没有运行时助手使用它)并且总是在setjmp中着陆(设置在函数之前) 或C++是如此脆弱,即使这样也不能保证工作正常,会破坏某些东西吗?或者,如果抛出实际异常,C++可能会中断吗?如果异常在本地抛出并立即捕获(在生成的程序集调用的运行时帮助程序中),那么它安全吗?或者仅仅因为有一些外来的框架,它就会拒绝工作,c++,exception,jit,setjmp,C++,Exception,Jit,Setjmp,例如: 在使用LojJMP/SETJMP时,理论上和实际上是安全的,在调用动态生成函数之前提供SETJMP,并且提供LoJMP从不通过依赖于RAII的C++函数传播(我必须确保在C++中没有运行时助手使用它),并且总是在SETJMP中着陆。(设置在函数之前) 本标准第18.10/4节规定: …longjmp(jmp_buf jbuf,int val)在本国际标准中具有更严格的行为。如果用catch和throw替换setjmp和longjmp将调用任何自动对象的非平凡析构函数,则setjmp调用对

例如:

在使用LojJMP/SETJMP时,理论上和实际上是安全的,在调用动态生成函数之前提供SETJMP,并且提供LoJMP从不通过依赖于RAII的C++函数传播(我必须确保在C++中没有运行时助手使用它),并且总是在SETJMP中着陆。(设置在函数之前)

本标准第18.10/4节规定:

…longjmp(jmp_buf jbuf,int val)在本国际标准中具有更严格的行为。如果用
catch
throw
替换
setjmp
longjmp
将调用任何自动对象的非平凡析构函数,则
setjmp
调用对具有未定义的行为

因此,不仅仅是RAII,还有任何使用非平凡析构函数的堆栈托管对象(即“资源”可能在构建后获得,但仍需要在销毁过程中释放,或者除了资源释放之外,还可能存在销毁的副作用,如日志记录)

还是C++是如此脆弱,以至于这不能保证工作正常,会破坏某些东西吗? 它应该根据上面关于琐碎析构函数的警告(这是一个很大的限制)工作

或者可能只有在抛出实际异常时C++才会中断?如果异常被本地抛出并立即被捕获(在生成的程序集调用的运行时助手),它是否安全?< /P>


这与<代码> SETJMP <代码> /Cord>LojMP行为无关,如果您抛出并捕获正常C++编译器生成的代码,则不应该有任何残留/随之而来的执行问题(RE)同样的方法用于封装的C++库,调用C++到/c++;异常可能被捕获在C++库的边界上,并转换成C可以处理的错误代码。< /P>有可能勾画出一些源代码/伪代码,来说明如何使用<代码> LojjMP/SETJMP ?这里是伪代码,所以,这意味着setjmp/longjmp只有在忽略它们之间的析构函数时才是不安全的?我担心的是,当析构函数与setjmp位于同一个函数中时,它会以某种方式损坏东西,因为谁知道“析构函数”使用了什么样的魔法来实现异常。P.S我还指的是整个潜在的堆栈展开事件(为支持它而发出的本机内部代码)@carsten“这意味着setjmp/longjmp只有在它们之间的析构函数被忽略时才是不安全的?”-不是它的意思……如果你指的是“未执行”,析构函数肯定会被“忽略”在跳转过程中,危险在于,如果忽略它们,则不会执行必要的销毁操作,并且标准的操作保障相当薄弱:如果所有相关的析构函数都不是微不足道的,则行为是未定义的。有关这意味着什么的解释,请参阅。“我担心当析构函数与setjmp在同一个函数中出现时,它会破坏某些东西,因为谁知道使用什么样的魔法来实现异常呢“-这不应该是一个问题:由编译器来确保如果/当您跳转回到那里时,本地作用域的析构函数能够正常运行。这是在跳转期间遗漏的内容,而不是在跳转之后,这是一个潜在的问题。”另外,我所说的“析构函数”也指的是整个潜在的堆栈展开(为支持它而发出的本机内部代码)“-如果在执行longjmp时堆栈状态有效,并且在设置JMP时堆栈状态仍然有效(即动态生成的代码没有损坏),则所有堆栈展开操作都将得到处理。

jmp_buf buf; // thread-local
char* msg;   // thread-local

// ... some C++ code here, potentially some RAII thingy

GeneratedFunc func = (GeneratedFunc)compile_stuff();
if (!setjmp(buf)) {
    // somewhere deep inside, it calls longjmp to jump back to the top function in case a problem happens
    func();
} else {
    printf("error: %s\n", msg);
    // do something about the error here
}

// some other C++ code