简体   繁体   English

函数调用中的字符串变量名,C ++

[英]Variable name to string in function call, C++

I'm expanding our internal debugging library, and I've run into an odd wall. 我正在扩展我们的内部调试库,而且我遇到了一个奇怪的问题。 I'd like to output a variable name as a string. 我想输出一个变量名作为字符串。 From elsewhere on this site, I found that a macro can be used to do this within a file: 从本网站的其他地方 ,我发现可以在文件中使用宏来执行此操作:

#define VarToStr(v) #v
...
printf("%s\n", VarToStr(MatName));

This outputs MatName . 这输出MatName But now let's try this through a function across files (Matrix is a defined type): 但现在让我们通过跨文件的函数来尝试这个(Matrix是一个定义的类型):

// DebugHelpers.h
#define VarToStr(v) #v
...
void PrintMatrix(const Matrix &InputMat)
{
    printf("%s\n", VarToStr(InputMat));
    ... // output InputMat contents
}

// DataAnalysis.cc
#include DebugHelpers.h
...
void AnalysisSubProgram342()
{
    Matrix MatName;
    ...
    PrintMatrix(MatName);
}

This outputs InputMat , instead of MatName . 这输出InputMat ,而不是MatName How can a function in another file get the variable name from the calling file? 另一个文件中的函数如何从调用文件中获取变量名?

While more complex solutions (wrapper classes, etc.) would be useful for the larger community, my implementation needs to minimize impact to preexisting code/classes. 虽然更复杂的解决方案(包装类等)对更大的社区有用,但我的实现需要最小化对预先存在的代码/类的影响。


Update: 更新:

Inspired by zenith's comments, I implemented both of his proposed solutions for comparison's sake and got both working quickly. 受天顶评论的启发,我为了比较而实施了他提出的两个解决方案,并且快速完成了工作。 The macro works well for simple outputs, while the function allows for more complex work (and type checking/overloading). 该宏适用于简单输出,而该功能允许更复杂的工作(以及类型检查/重载)。 I hadn't known that preprocessor macros could be so complex. 我不知道预处理器宏可能如此复杂。 I'll remember both for future use. 我会记住两者以备将来使用。 Thanks ! 谢谢 !

You can't. 你不能。 Neither C nor C++ retain variable names at runtime. C和C ++都不会在运行时保留变量名。

All your macros are doing is substituting text which happens at compile time. 您的所有宏都在替换在编译时发生的文本。

As mentioned by others, C++ doesn't support runtime reflection, so if you want to have a string whose contents will only be known at runtime (which is when the call to PrintMatrix will happen), you need to pass it as an argument . 正如其他人所提到的,C ++不支持运行时反射,因此如果你想拥有一个只在运行时知道其内容的字符串(即调用PrintMatrix时候),你需要将它作为参数传递

And because you always know what your variables' names are you don't need the VarToStr macro: 而且因为你总是知道变量的名称是什么,所以你不需要VarToStr宏:

// DebugHelpers.h
void PrintMatrix(const Matrix &InputMat, const char* MatName)
{
    printf("%s\n", MatName);
    ... // output InputMat contents
}

// DataAnalysis.cc
#include DebugHelpers.h
...
void AnalysisSubProgram342()
{
    Matrix MatName;
    ...
    PrintMatrix(MatName, "MatName");
}

But there's another choice : make PrintMatrix a macro itself, since it's only a debug thing anyway: 但还有另一种选择 :让PrintMatrix成为一个宏本身,因为它只是一个调试的东西:

// DebugHelpers.h
#define PRINT_MATRIX(InputMat)\
printf(#InputMat "\n");\
... // output InputMat contents


// DataAnalysis.cc
#include DebugHelpers.h
...
void AnalysisSubProgram342()
{
    Matrix MatName;
    ...
    PRINT_MATRIX(MatName);
}

Now after preprocessing, AnalysisSubProgram342 will look like this: 现在经过预处理后, AnalysisSubProgram342将如下所示:

void AnalysisSubProgram342()
{
    Matrix MatName;
    ...
    printf("MatName\n");
    ... // output InputMat contents
}

In general you cannot do that (getting the name of a variable at runtime, from eg its address or in C++ its reference). 通常,您不能这样做(在运行时获取变量的名称,例如从其地址或在C ++中获取它的引用)。

I am focusing on Linux: 我专注于Linux:

However, on Linux (and GNU glibc based systems), for global variables (and functions), you might use the GNU specific dladdr(3) function. 但是,在Linux(和基于GNU glibc的系统)上,对于全局变量(和函数),您可以使用GNU特定的dladdr(3)函数。

If all the relevant code was compiled with -g (to get debug info), you might parse the debug information in DWARF format (perhaps also using __builtin_frame_address , etc.). 如果所有相关代码都是使用-g编译的(以获取调试信息),则可能会以DWARF格式解析调试信息(也许还使用__builtin_frame_address等)。 With some pain, you might be able to get the name of some local variables from its address on the call stack . 有些痛苦,您可能能够从调用堆栈上的地址获取一些局部变量的名称。 This would be a significant effort (probably months of work). 这将是一项重大的努力(可能是几个月的工作)。 Ian Taylor's libbacktrace (inside GCC) might be useful as a starting point. Ian Taylor的libbacktrace (在GCC内部)可能是一个有用的起点。

You could also start (assuming everything is compiled with -g ), with eg popen(3) , a gdb -p debugging process. 您也可以启动(假设所有内容都使用-g编译),例如popen(3)gdb -p调试过程。

Notice that recent GDB debugger is scriptable in Python or Guile, so practically speaking developing Python or Guile functions for GDB would be quicker. 请注意,最近的GDB调试器可以在Python或Guile中编写脚本,因此实际上,为GDB开发Python或Guile函数会更快。

You could also simply add debug output like here . 您也可以像这里一样添加调试输出。

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

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