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

时间:2016-01-21 08:00:03

标签: object corrupt clips

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

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);

然后,我查看事实列表并检索所需信息。在那里,我还以下列方式为上述每个事实制作了另一个“子查询”

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事实地址保存在向量中然后处理它。由于到目前为止我找不到关于我的理论的任何信息,我想在这里问一下。

所以我的问题非常简单,并且会是:如果我在彼此之后执行两个查询,那么一旦我调用第二个查询,第一个查询的检索信息是否会失效?

1 个答案:

答案 0 :(得分:0)

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

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

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

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

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

“高级编程指南”第1.4节中有关于垃圾收集的一些其他信息。