有件事让我很吃惊,那就是如果我在运行时调试期间将捕获lambda(带有重载函数调用操作符的构造对象的语法糖)赋给std::function,编译器会告诉我该函数/类的成员名称:
std::function<void()> callable1;
std::function<void()> callable2;
std::function<void()> callable3;
int main()
{
int aa = 1;
int bb = 1;
callable1 = [dog = aa, cat = bb]() {
return 5;
};
callable2 = [kitchen = aa, lounge = bb]() {
return 5;
};
callable3 = [hammer = aa, sickle = bb]() {
return 5;
};
std::vector < std::function<void()>> callables;
callables.push_back(callable1);
callables.push_back(callable2);
callables.push_back(callable3);
}
我在编译器上看到的是:
这是非常令人印象深刻的,我想知道它是如何做到的。无论使用什么技术,我猜都是一种非常想学习的反射方法,因为c++没有反射特性。有趣的是,在我的机器上,无论是调试模式还是发布模式,std::函数的大小都是64字节,所以我不知道他们是如何将字符串存储为成员的名称的。
1条答案
按热度按时间fkvaft9z1#
编译器如何知道std::函数中捕获的变量的名称?
在Linux上,
gcc -g
将向ELF executable添加其他部分。这些部分包含DWARF的程序调试信息。例如,在
.debug_str
中,.debug_info
中的调试信息引用了字符串:调试器检查
std::function
,找到一个函数指针。然后扫描.debug_info
中与该指针关联的调试信息的所有条目。然后分析该信息并在IDE中显示分析结果。我怎样才能得到这些信息?我是指字符串名称和偏移量等?
通常,也是最常见的,您可以通过调试器 * 访问这些信息。调试器是访问这些信息的工具。您可以使用libdwarf和efitools从您自己的程序访问这些信息。
例如,您可以在程序和
open(argv[0])
中包含ELF库,然后解析您自己的ELF可执行文件中的调试部分并显示有关它的信息。通常,在显示有关C++异常的良好堆栈跟踪时,需要检查ELF本身。