Merge pull request #2 from wanmeihuali/hotfix/stack_overflow_better_solution

a better solution for ISUEE-1433
release/4.3a0
wanmeihuali 2023-02-02 13:46:29 -08:00 committed by GitHub
commit 21a8faa25d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 31 additions and 38 deletions

View File

@ -28,7 +28,6 @@
#include <string> #include <string>
#include <queue> #include <queue>
#include <deque>
namespace gtsam { namespace gtsam {
@ -114,21 +113,24 @@ namespace gtsam {
BayesTree(const This& other); BayesTree(const This& other);
~BayesTree() { ~BayesTree() {
nodes_.clear(); // clear the map manually, as we cannot control the order of destruction in the map
for (auto&& root: roots_) { for (auto&& root: roots_) {
std::queue<Clique*> bfs_queue; std::queue<sharedClique> bfs_queue;
std::deque<Clique*> topological_order;
bfs_queue.push(root.get()); // first, move the root to the queue
bfs_queue.push(root);
root = nullptr;
// do a BFS on the tree, for each node, add its children to the queue, and then delete it from the queue
// So if the reference count of the node is 1, it will be deleted, and because its children are in the queue,
// the deletion of the node will not trigger a recursive deletion of the children.
while (!bfs_queue.empty()) { while (!bfs_queue.empty()) {
Clique* current = bfs_queue.front(); auto current = bfs_queue.front();
bfs_queue.pop(); bfs_queue.pop();
topological_order.push_front(current); for (auto child: current->children) {
for (auto&& child: current->children) { bfs_queue.push(child);
bfs_queue.push(child.get());
} }
} }
for (auto&& clique: topological_order) {
clique->children.clear();
}
} }
} }

View File

@ -26,7 +26,6 @@
#include <mutex> #include <mutex>
#include <optional> #include <optional>
namespace gtsam { namespace gtsam {
// Forward declarations // Forward declarations

View File

@ -9,7 +9,6 @@
#pragma once #pragma once
#include <deque>
#include <queue> #include <queue>
#include <gtsam/base/Testable.h> #include <gtsam/base/Testable.h>
#include <gtsam/base/FastVector.h> #include <gtsam/base/FastVector.h>
@ -48,8 +47,7 @@ class ClusterTree {
Cluster() : problemSize_(0) {} Cluster() : problemSize_(0) {}
virtual ~Cluster() { virtual ~Cluster() {}
}
const Cluster& operator[](size_t i) const { const Cluster& operator[](size_t i) const {
return *(children[i]); return *(children[i]);
@ -169,22 +167,20 @@ class ClusterTree {
virtual ~ClusterTree() { virtual ~ClusterTree() {
// use default destructor which recursively deletes all nodes with shared_ptr causes stack overflow. // use default destructor which recursively deletes all nodes with shared_ptr causes stack overflow.
// so for each tree, we do a BFS to get sequence of nodes to delete, and clear their children first. // so for each tree, we first move the root into a queue; then we do a BFS on the tree with the queue;
// for each node iterated, if its reference count is 1, it will be deleted while its children are still in the queue.
// so that the recursive deletion will not happen.
for (auto&& root : roots_) { for (auto&& root : roots_) {
std::queue<Cluster*> bfs_queue; std::queue<sharedNode> bfs_queue;
std::deque<Cluster*> topological_order; bfs_queue.push(root);
bfs_queue.push(root.get()); root = nullptr;
while (!bfs_queue.empty()) { while (!bfs_queue.empty()) {
auto node = bfs_queue.front(); auto node = bfs_queue.front();
topological_order.push_front(node);
bfs_queue.pop(); bfs_queue.pop();
for (auto&& child : node->children) { for (auto child : node->children) {
bfs_queue.push(child.get()); bfs_queue.push(child);
} }
} }
for (auto&& node : topological_order) {
node->children.clear();
}
} }
} }

View File

@ -121,24 +121,21 @@ namespace gtsam {
public: public:
~EliminationTree() { ~EliminationTree() {
// default destructor will cause stack overflow for deletion of large trees // use default destructor which recursively deletes all nodes with shared_ptr causes stack overflow.
// so we delete the tree explicitly by first BFSing the tree to determine the topological order // so for each tree, we first move the root into a queue; then we do a BFS on the tree with the queue;
// and then clearing the children of each node in topological order // for each node iterated, if its reference count is 1, it will be deleted while its children are still in the queue.
// so that the recursive deletion will not happen.
for (auto&& root : roots_) { for (auto&& root : roots_) {
std::queue<Node*> bfs_queue; std::queue<sharedNode> bfs_queue;
std::deque<Node*> topological_order; bfs_queue.push(root);
bfs_queue.push(root.get()); root = nullptr;
while (!bfs_queue.empty()) { while (!bfs_queue.empty()) {
Node* node = bfs_queue.front(); auto node = bfs_queue.front();
bfs_queue.pop(); bfs_queue.pop();
topological_order.push_front(node);
for (auto&& child : node->children) { for (auto&& child : node->children) {
bfs_queue.push(child.get()); bfs_queue.push(child);
} }
} }
for (auto&& node : topological_order) {
node->children.clear();
}
} }
} }
/// @name Standard Interface /// @name Standard Interface
@ -179,7 +176,6 @@ namespace gtsam {
/** Swap the data of this tree with another one, this operation is very fast. */ /** Swap the data of this tree with another one, this operation is very fast. */
void swap(This& other); void swap(This& other);
protected: protected:
/// Protected default constructor /// Protected default constructor
EliminationTree() {} EliminationTree() {}