DeleteInterpProc调用活动的评估
DeleteInterpProc called with active evals
我正在编写一个执行tcl脚本的程序。当脚本有exit
命令时,程序崩溃并出现以下错误
DeleteInterpProc called with active evals
Aborted
我正在调用Tcl_EvalFile(m_interpreter, script.c_str())
,其中脚本是文件名。我也尝试了Tcl_Eval
与参数解释器和"源文件名"。结果是一样的。其他tcl命令(例如:put)解释器正常执行。如何解决这个问题?
#include <tcl.h>
#include <iostream>
int main() {
Tcl_Interp *interp = Tcl_CreateInterp();
//Tcl_Preserve(interp);
Tcl_Eval (interp, "exit");
//Tcl_Release(interp);
std::cout << "11111111111" << std::endl;
return 0;
}
这是一个简单的例子。不打印"11111111111"。据我所知,当调用Tcl_Eval (interp, "exit");
时,整个程序将退出。添加Tcl_Preserve
和Tcl_Release
后,结果相同。
问题是解释器,Tcl代码的执行上下文,正在从它自己的脚下被删除;这使得它非常困惑!至少你得到了一个干净的恐慌/中止,而不是一个恶心的难以复制的崩溃。
最简单的修复方法可能是:
Tcl_Preserve(m_interpreter);
// Your code that calls Tcl_EvalFile(m_interpreter, script.c_str())
// and deals with the results.
Tcl_Release(m_interpreter);
请注意,在Tcl_Release
之后,Tcl_Interp
句柄可能指向已删除的内存。(是的,将Tcl_Preserve
/Tcl_Release
包裹在RAII中是合理的。)
如果您希望允许您的代码在脚本执行exit
之后运行,则必须采取额外的步骤。特别是,标准Tcl exit
命令没有设计成导致返回到调用上下文:它将导致进程调用_exit(2)
系统调用。要改变它的行为,替换它:
// A callback function that implements the replacement
static int
MyReplacementExit(ClientData unused, Tcl_Interp *interp, int argc, const char *argv[])
{
// We ought to check the argument count... but why bother?
Tcl_DeleteInterp(interp);
return TCL_OK;
}
int main() {
Tcl_Interp *interp = Tcl_CreateInterp();
// Install that function over the standard [exit]
Tcl_CreateCommand(interp, "exit", MyReplacementExit, NULL, NULL);
// Important; need to keep the *handle* live until we're finished
Tcl_Preserve(interp);
// Or run whatever code you want here...
Tcl_Eval(interp, "exit");
// Important piece of cleanup code
if (!Tcl_InterpDeleted(interp))
Tcl_DeleteInterp(interp);
Tcl_Release(interp);
// After this point, you *MUST NOT* use interp
std::cout << "11111111111" << std::endl;
return 0;
}
在这些场景中进行内存管理的规则在Tcl_CreateInterp
的手册页中列出。(这是8.6的手册页,但至少从20多年前的Tcl 7.0开始,相关规则就已经成立了。)一旦解释器被删除,你就不能再指望执行任何命令或访问其中的任何变量;
最好替换(隐藏)exit
命令并创建自己的exit
命令,以便优雅地退出程序。我不太擅长C和Tcl C Api,但我希望这能帮助你。
以Eggdrop为例,使用die
命令优雅退出。
- std::condition_variable::wait()如何评估给定的谓词
- c++11评估顺序(未定义的行为)
- 如何使用"equal to"以外的评估编写开关语句
- 当可输入框在窗口中处于活动状态时获得通知的任何方法
- 嵌套 if 中没有返回评估
- 懒惰的参数评估try_emplace?
- 在实践中,在运行时为零的乘法中是否有任何"lazy"评估
- 如何改进一堆在已知值范围内评估变量的 else-if 条件?
- C++17:使用 std::optional 来评估枚举是否包含值
- CNTK:->转发或 ->评估某些电脑上的崩溃,而不是其他电脑上的崩溃
- ConstexPR :GCC比Clang更努力地评估ConstexPR
- "错误 (活动) E1696 无法打开源文件 "stdafx.h"--
- glBindTexture 是否覆盖活动纹理单元的内容
- C++:Constexpr斐波那契数列评估
- C++能保证论点评估的原子性吗?
- 在编译时评估函数开销的通用方法
- 如何使用 std::forward 精确地评估参数包的扩展?
- MSVC 在不知道类型的情况下评估上下文(和错误)
- C++评估顺序优化是否意味着对不同的操作数使用不同的内核?
- DeleteInterpProc调用活动的评估