Обрезки нескольких запросов EnvEval делают недействительными предыдущие объекты результатов?

У меня была еще одна странная проблема, которую я уже решил. Но я не уверен, что просто удачно исправил это или действительно понимаю, что происходит. Итак, в основном я выполняю запрос по моим фактам через:

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 в векторе, а затем обработать его. Поскольку я не мог найти никакой информации о своей теории, я хотел спросить здесь.

Итак, мой вопрос довольно прост и будет заключаться в следующем: Если я выполняю два запроса друг за другом, становится ли полученная информация первого запроса недействительной, как только я вызываю второй запрос?


person steve    schedule 21.01.2016    source источник


Ответы (1)


Функция EnvEval должна быть отмечена в документации как запускающая сборку мусора, но это не так. CLIPS внутренне представляет строки, целые числа, числа с плавающей запятой и другие примитивы, аналогичные другим языкам (например, Java), которые допускают экземпляры классов, таких как String, Integer и Float. Поскольку эти значения создаются динамически, они должны быть подвергнуты сборке мусора, когда они больше не используются. Внутри CLIPS использует счетчики ссылок, чтобы определить, ссылаются ли на эти значения, но когда эти значения возвращаются в код пользователя, невозможно узнать, ссылаются ли на них, без каких-либо действий со стороны пользовательского кода.

Когда вы вызываете EnvEval, возвращаемое им значение освобождается от сборки мусора. Это не исключение при следующем вызове EnvEval. Таким образом, если вы немедленно обрабатываете возвращаемое значение или сохраняете его (т. е. выделяете память для строки и копируете значение из CLIPS или сохраняете адреса фактов из мультиполя в массиве), вам не нужно беспокоиться о значении, возвращаемом функцией CLIPS собирает мусор последующим вызовом EnvEval.

Если вы хотите выполнить серию вызовов EnvEval (или другую функцию CLIPS, которая может инициировать сборку мусора), не беспокоясь о сборке мусора, оберните вызовы в EnvIncrementGCLocks/EnvDecrementGCLocks

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

Сборка мусора для всех значений, возвращаемых вашему коду, будет временно отключена, пока вы выполняете вызовы, а затем, когда вы закончите, вызвав EnvDecrementGCLocks, значения будут удалены сборщиком мусора.

Дополнительная информация о сборке мусора содержится в разделе 1.4 Advanced Programming Guide.

person Gary Riley    schedule 21.01.2016