可以将深层呼叫堆栈的代码视为反图案



我们正在围绕LLVM库进行研究,我们发现IR库有时可以访问堆栈最多29个方法。

有时候,当我在iOS框架中看到一些崩溃时,我也会观察到很深的呼叫堆栈。

我的问题是,我们是否可以推释一下,设计的代码是否有问题,该代码将自己称为如此之大的深度。

这是一个示例:

/usr/local/LLVM/llvm/unittests/IR/AttributesTest.cpp:54
  /usr/local/LLVM/llvm/lib/IR/LLVMContext.cpp:162
    /usr/local/LLVM/llvm/lib/IR/LLVMContext.cpp:162
      /usr/local/LLVM/llvm/lib/IR/LLVMContextImpl.cpp:54
        /usr/local/LLVM/llvm/lib/IR/LLVMContextImpl.cpp:59
          /usr/local/LLVM/llvm/lib/IR/Module.cpp:60
            /usr/local/LLVM/llvm/lib/IR/Module.cpp:62
              /usr/local/LLVM/llvm/lib/IR/Module.cpp:456
                /usr/local/LLVM/llvm/lib/IR/Function.cpp:350
                  /usr/local/LLVM/llvm/lib/IR/BasicBlock.cpp:98
                    /usr/local/LLVM/llvm/include/llvm/ADT/ilist.h:282
                      /usr/local/LLVM/llvm/include/llvm/ADT/ilist.h:267
                        /usr/local/LLVM/llvm/lib/IR/SymbolTableListTraitsImpl.h:76
                          /usr/local/LLVM/llvm/lib/IR/BasicBlock.cpp:90
                            /usr/local/LLVM/llvm/lib/IR/SymbolTableListTraitsImpl.h:58
                              /usr/local/LLVM/llvm/lib/IR/ValueSymbolTable.cpp:75
                                /usr/local/LLVM/llvm/lib/IR/ValueSymbolTable.cpp:47
                                  /usr/local/LLVM/llvm/include/llvm/Support/Casting.h:132
                                    /usr/local/LLVM/llvm/include/llvm/Support/Casting.h:112
                                      /usr/local/LLVM/llvm/include/llvm/Support/Casting.h:122
                                        /usr/local/LLVM/llvm/include/llvm/Support/Casting.h:96
                                          /usr/local/LLVM/llvm/include/llvm/IR/Value.h:777
                                            /usr/local/LLVM/llvm/include/llvm/Support/Casting.h:132
                                              /usr/local/LLVM/llvm/include/llvm/Support/Casting.h:122
                                                /usr/local/LLVM/llvm/include/llvm/Support/Casting.h:75
                                                  /usr/local/LLVM/llvm/include/llvm/IR/Value.h:771
                                                    /usr/local/LLVM/llvm/include/llvm/Support/Casting.h:132
                                                      /usr/local/LLVM/llvm/include/llvm/Support/Casting.h:122
                                                        /usr/local/LLVM/llvm/include/llvm/Support/Casting.h:75
                                                          /usr/local/LLVM/llvm/include/llvm/IR/Value.h:759

P.S。示例调用堆栈实际上是由llvmcontext类的破坏者产生的:LLVMContext::~LLVMContext()。这是Java World的一个非常古老的帖子的另一个示例:Java Call stack - http to jdbc作为图片。

我的问题是,我们是否可以推释一下,设计的代码是否有问题,该代码将自己称为如此之大的深度。

我要去肢体说"是",但是您的问题和答案存在问题。

概念原因是否有戴上帽子的原因。您可以推荐循环是否终止;您可以证明它确实可以,也可以。您可以推论是否存在种族条件。您无法推论是否存在可能存在的东西。

没有标准,没有指标,没有权威会告诉您通话堆栈太深了。请记住,几乎可以避免任何任何呼叫堆栈:呼叫堆栈是图书馆的"分解"(如果愿意的话)的工件。可以想象用宏或C 模板替换函数调用。相同的逻辑效果,指令数量略低。也许更便宜,因为在线或更昂贵,因为重复的代码。但是至少堆栈指针没有改变!

因此,我将您的问题解释为:是一个大的调用堆栈,相对于实现的功能,理由仔细检查代码是否不必要的复杂性?对此,我说是的。

面对您描述的情况,我想知道其中一些电话是否是"经理"功能:某种概括的包装器没有做得太多。我记得几年前读了一个编组库,在那里 write (2)的呼叫堆栈是14个深的。大多数代码除了将数据调整为另一个抽象之外,什么都没有做任何事情。

无巧合:该库和您的库都是C 。C 使进行隐式函数调用变得容易,而破坏者就是一个示例。如果您将其作为C功能写作,我敢打赌,它会很长。在释放记忆之前,破坏者也很容易进行许多"清理"。在C中,您可能只打了免费(3)几次,然后使用它。

因此,这并不是呼叫堆栈深度本身这是一个问题。但是IMO您的本能是正确的:在少量功能上,大型呼叫堆栈表示一种超组织的意大利面条代码。重新查看功能当然不会受到伤害,也许正在寻找减少抽象数量的方法。

通常,是的,当我看到深层呼叫堆栈时,我会感到可疑,原因与James K. Lowden相似。

但是您的示例是规则的例外。看来您的代码正在遍历源代码的表示。源代码包含深度嵌套的结构,您的代码正在递归遍历这些结构。因此,呼叫堆栈将与代码嵌套一样深。这是完全期望和可以的,尽管我希望您有很多分配给堆栈的记忆。

最新更新