简体   繁体   English

如何访问调用堆栈?

[英]How to access the call stack?

I have a tree data structure composed by parent nodes and child nodes, something like this: 我有一个由父节点和子节点组成的树数据结构,如下所示:

<Node1>
  <Node2/>

  <Node3>
    <Node4/>
  </Node3>
</Node1>

And to parse the structure i use a μ-recursive function: 要解析结构,我使用μ递归函数:

void RecursiveFunction(NodeT node)
{
    if(node.has_child())
        RecursiveFunction(node.child());
}

When i call RecursiveFunction passing as parameter, for example, Node2 i want to have the access to the father (Node1) data without storing these data using additional data structures, because the data of the first node has been stored on the call stack before making the recursive call. 当我调用RecursiveFunction作为参数传递时,例如,Node2我希望能够访问父(Node1)数据而不使用其他数据结构存储这些数据,因为第一个节点的数据在制作之前已经存储在调用堆栈中递归调用。 So I need to access the call stack to read data of Node1 while I am parsing Node2 failing direct access to the father, and so on. 因此,当我解析Node2无法直接访问父亲时,我需要访问调用堆栈以读取Node1的数据,依此类推。

For example, if i'm parsing Node4: 例如,如果我正在解析Node4:

void RecursiveFunction(NodeT node)
{
    /* Access to Node3 and Node1 data...

    if(Node4.has_child())
        RecursiveFunction(Node4.child()); */
}

Is it possible? 可能吗? In what way? 以什么方式?

Thanks. 谢谢。

It would be possible, but it would be quite dangerous to do so. 这是可能的,但这样做会非常危险。 This is mainly because you want to mess with the process stack. 这主要是因为你想搞乱进程堆栈。 Also I don't think there are any library functions to do so, that being said you would have to do some pointer arithmetics to achieve that. 另外我不认为有任何库函数可以这样做,据说你必须做一些指针算术来实现这一点。

Even if you would find a way to access the data from the calling function, it would not be easy for any other programmer to understand what you do. 即使您找到了一种从调用函数访问数据的方法,任何其他程序员都不容易理解您的操作。

I would suggest to replace the recursion by an iteration which should allow you to express clearly what you want to do. 我建议通过迭代替换递归,这应该允许您清楚地表达您想要做的事情。 See Way to go from recursion to iteration for more information. 有关更多信息,请参阅从递归到迭代的方法。

Accessing the callstack is a little bit of overengineering for me. 访问callstack对我来说有点过度工程。 Convert the function from recursive to iterative and use your own stack. 将函数从递归转换为迭代并使用您自己的堆栈。 The stack shall contain an instance of NodeT and integer value informing the function, how many of the node's children has been already processed. 堆栈应包含一个NodeT实例和通知函数的整数值,已经处理了多少个节点的子节点。 If this value is lower than node's child count, loop shall increment this value and add the next child to the stack. 如果此值低于节点的子计数,则循环将递增此值并将下一个子项添加到堆栈。 Otherwise it shall process the node and then pop it from the stack. 否则它将处理节点,然后从堆栈中弹出它。

The other advantage is, that you're no longer restricted by size of the program's stack and you can process way more nested structures if there is such a need. 另一个优点是,您不再受程序堆栈大小的限制,并且如果有这样的需要,您可以处理更多嵌套结构。 Otherwise you risk, well, let's not be affraid to say, stack overflow. 否则你冒险,好吧,让我们不要害怕说,堆栈溢出。

If you want or must (eg homework requirement?) stick with recursion, add the parent node as a second argument to your function which defaults to NULL , indicating that the current node is the root node. 如果您想要或必须(例如家庭作业?)坚持递归,请将父节点作为第二个参数添加到您的函数中,默认为NULL ,表示当前节点是根节点。 Ie: 即:

void RecursiveFunction(NodeT const& node, NodeT const* parentPtr=NULL)
{
    if(node.has_child())
        RecursiveFunction(node.child(), &node);
}

Note that I modified your function to accept the first argument by reference to const, otherwise you create a lot of copies of your tree. 请注意,我修改了您的函数以通过引用const接受第一个参数,否则您将创建树的许多副本。

The call stack is used for function parameters as well*, so use that to build the chain: 调用堆栈也用于函数参数*,因此使用它来构建链:

struct chain {
  NodeT* node;
  chain const* parent;
}
void RecursiveFunction(chain const& c)
{
    if(c.node->has_child()) {
       chain child = { c.node->child(), &c };
        RecursiveFunction(child);
    }
}

[*] At least conceptually; [*]至少在概念上; actual implementations may differ. 实际实施可能不同。 In any case this C++ code is portable, unlike low-level hacks. 无论如何,这个C ++代码是可移植的,与低级别的黑客不同。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM