Sta*_*ich 6 callstack anti-patterns llvm
我们正在围绕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
Run Code Online (Sandbox Code Playgroud)
PS示例调用堆栈实际上是由LLVMContext类的析构函数生成的:LLVMContext::~LLVMContext().这是来自Java世界的一篇非常古老的帖子的另一个例子:Java调用栈 - 从HTTP到JDBC作为图片.
我的问题是,我们是否可以推断一个代码的设计是否存在问题,而这个代码的设计自称是如此之大.
我要站出来说"是",但你的问题和答案都有问题.
关于是否可能没有多少挂帽的概念原因.你可以推断循环是否终止; 你可以证明它有或没有.您可以判断是否存在竞争条件.你不能理性的东西是否可能存在.
没有标准,没有指标,没有权限会告诉你调用堆栈有多深.请记住几乎任何调用堆栈都是可以避免的:调用堆栈是库的"因子分解"(如果你愿意)的工件.可以想象用宏或C++模板替换函数调用.逻辑效果相同,指令数略低.也许更便宜,因为在线,或更昂贵,因为重复的代码.但至少堆栈指针没有改变!
所以我将你的问题解释为:相对于已实现的功能,一个大的调用堆栈是否有理由仔细检查代码是否存在不必要的复杂性? 对此,我说是的.
面对像你描述的那样的情况,我想知道这些调用中的一些是否是"管理器"函数:某种通用包装器并没有做太多.我记得几年前读过一个编组库,其中写入(2)的调用栈是14深.除了将数据混合到另一个抽象中之外,大多数代码都没有做任何事情.
没有巧合:那个库和你的都是C++.C++使得隐式函数调用变得容易,而析构函数就是一个例子.如果你把析构函数写成C函数,我敢打赌它会长而扁平.在释放内存之前,析构函数也倾向于做很多"清理"; 在C中,你可能只需要几次调用free(3),并完成它.
因此,调用堆栈深度本身并不是一个问题.但是IMO你的直觉是正确的:一个大的调用栈代表少量的功能表明一种超级组织的意大利面条代码.重新审视功能肯定不会受到伤害,也许还在寻找减少抽象数量的方法.
| 归档时间: |
|
| 查看次数: |
563 次 |
| 最近记录: |