有没有办法从d?
中的函数或方法中获取调用Object示例:
class Foo
{
public void bar()
{
auto ci = whoCalledMe();
// ci should be something that points me to baz.qux, _if_ baz.qux made the call
}
}
class Baz
{
void qux()
{
auto foo = new Foo();
foo.bar();
}
}
问题:
whoCalledMe
之类的内容?如果是这样,它叫什么?可替换地;
debug_backtrace
?答案 0 :(得分:5)
要扩展CyberShadow said,因为您可以使用__FUNCTION__
获取函数的完全限定名称,您还可以使用mixin将函数作为符号获取:
import std.stdio;
import std.typetuple;
void callee(string file=__FILE__, int line=__LINE__, string func=__FUNCTION__)()
{
alias callerFunc = TypeTuple!(mixin(func))[0];
static assert(&caller == &callerFunc);
callerFunc(); // will eventually overflow the stack
}
void caller()
{
callee();
}
void main()
{
caller();
}
堆栈将在这里溢出,因为这两个函数最终会无限递归地相互调用。
答案 1 :(得分:4)
无法直接获取有关“来电者”的信息。你可能有幸从调用堆栈获取地址,但这是一个低级操作,取决于你的程序是否使用堆栈帧编译。获得地址后,理论上可以将其转换为函数名和行号,前提是调试符号可用于程序的二进制文件,但(再次)这是高度特定于平台的,并且取决于用于编译程序的工具链
作为替代方案,您可能会发现这有用:
void callee(string file=__FILE__, int line=__LINE__, string func=__FUNCTION__)()
{
writefln("I was called by %s, which is in %s at line %d!", func, file, line);
}
void caller()
{
// Thanks to IFTI, we can call the function as usual.
callee();
}
但请注意,您不能将此技巧用于非final类方法,因为每次调用该函数都会生成一个新的模板实例(并且编译器需要事先知道类的所有虚方法的地址)
答案 2 :(得分:2)
查找调用程序是调试程序所做的事情,通常需要在打开符号调试信息开关的情况下构建程序。阅读调试信息以解决这个问题是高度依赖系统的,而且非常先进。
异常展开机制也可以找到调用者,但是不为不需要它们的函数生成那些表,并且这些表不包含函数的名称。