剪辑多个 EnvEval 查询会使以前的结果对象无效?

Clips multiple EnvEval queries invalidate previous result objects?

我有另一个奇怪的问题,我已经解决了。但我不确定我只是幸运地修复了它,还是我真的了解发生了什么。所以基本上我通过以下方式对我的事实进行了查询:

DATA_OBJECT decay_tree_fact_list;
std::stringstream clips_query;
clips_query << "(find-all-facts ((?f DecayTree)) TRUE)";
EnvEval(clips_environment_, clips_query.str().c_str(), &decay_tree_fact_list);

然后我浏览事实列表并检索所需的信息。我还通过以下方式为上面找到的每个事实制作了另一个 "subquery"

DATA_OBJECT spin_quantum_number_fact_list;
std::stringstream clips_query;
clips_query << "(find-fact ((?f SpinQuantumNumber)) (= ?f:unique_id "
  << spin_quantum_number_unique_id << "))";
EnvEval(clips_environment_, clips_query.str().c_str(),
  &spin_quantum_number_fact_list);

这对于第一个 DecayTree 事实来说一切正常,无论我从哪个位置开始,但对于下一个它崩溃了,因为事实地址是伪造的。我将问题追溯到我所做的子查询。所以我解决问题的方法是将所有 DecayTree 事实地址保存在一个向量中,然后对其进行处理。由于到目前为止我找不到任何关于我的理论的信息,所以我想在这里问一下。

所以我的问题很简单,就是:如果我依次执行两个查询,第一个查询的检索信息是否会在我执行后立即失效调用第二个查询?

EnvEval 函数应该在文档中标记为触发垃圾回收,但事实并非如此。 CLIPS 在内部表示字符串、整数、浮点数和其他类似于其他语言(例如 Java)的原语,它们允许 类 的实例,例如 String、Integer 和 Float。由于这些值是动态创建的,因此当它们不再使用时需要进行垃圾回收。在内部 CLIPS 使用引用计数来确定这些值是否被引用,但是当这些值返回给用户代码时,如果没有用户代码的某些操作,就不可能知道它们是否被引用。

当您调用 EnvEval 时,它 returns 的值免于垃圾回收。下次调用 EnvEval 时不会免除。因此,如果您立即处理返回的值或保存它(即为字符串分配存储空间并从 CLIPS 复制值或将多字段中的事实地址保存在数组中),那么您无需担心返回值CLIPS 被后续的 EnvEval 调用垃圾收集。

如果您想执行一系列 EnvEval 调用(或其他可能触发垃圾回收的 CLIPS 函数)而不必担心值被垃圾回收,请将调用包装在 EnvIncrementGCLocks/EnvDecrementGCLocks

EnvIncrementGCLocks(theEnv);
   ... Your Calls ...
EnvDecrementGCLocks(theEnv);  

在您进行调用时,将暂时禁用对返回到您的代码的所有值的垃圾收集,然后当您通过调用 EnvDecrementGCLocks 完成时,这些值将被垃圾收集。

高级编程指南的第 1.4 节中有一些关于垃圾收集的附加信息。