c++ - 给定一个包含 lambda 函数的调用堆栈,如何确定其来源?
问题描述
假设您有一些代码推送到这样的队列中:
template <typename T>
void submitJobToPool(T callable)
{
someJobQueue.push(callable)
}
...后来:
template <typename T>
void runJobFromPool(T callable)
{
auto job = someJobQueue.pop();
job();
}
现在假设代码由于job()
调用内部的一些错误而崩溃。如果提交的作业是普通函数,调用堆栈可能如下所示:
void myFunction() 0x345678901
void runJobFromPool() 0x234567890
int main(int, char**) 0x123456789
很容易看出是什么函数在这里崩溃了。如果它是一个仿函数,它会很相似,但operator()
在某处有一个(忽略内联)。但是,对于 lambda...
void lambda_a7009ccf8810b62b59083b4c1779e569() 0x345678901
void runJobFromPool() 0x234567890
int main(int, char**) 0x123456789
这不是那么容易调试。如果发生时附加了调试器,或者有可用的核心转储,则该信息可用于派生哪个 lambda 崩溃,但该信息并不总是可用。据我所知,拆卸是确定由此而崩溃的少数几种方法之一。
我必须使它变得更好的想法是:
- 使用
addr2line
平台支持的工具。这有时有效,有时无效。 - 将所有 lambda 封装在函子中(至少可以说并不理想)。
- 不使用 lambdas(同样,不理想)。
- 使用编译器扩展为 lambda 赋予更有意义的名称/添加调试信息。
第四个选项听起来很有希望,所以我做了一些调查,但找不到任何东西。如果重要的话,我可用的编译器是 clang++ 5.0 和 MSVC 19 (Visual Studio 2015)。
我的问题是,还有哪些其他工具/技术可以帮助将带有 lambda 函数的调用堆栈映射到相应的源代码行?
解决方案
恐怕这是不可能的。您应该设计自己的技术如何在 lamdas 中存储所需的信息。您的选项 2 适合这里。你可以看看它是如何谷歌:https ://cs.chromium.org/chromium/src/base/task_scheduler/post_task.h
以下是非常原始的方法(https://ideone.com/OFCgAq)
#include <iostream>
#include <stack>
#include <functional>
std::stack<std::function<void(void)>> someJobQueue;
template <typename T>
void submitJobToPool(std::string from_here, T callable) {
someJobQueue.push(std::bind([callable](std::string from_here) { callable(); }, from_here));
}
void runJobFromPool() {
auto job = someJobQueue.top();
someJobQueue.pop();
job();
}
int main() {
submitJobToPool(__func__, [](){ std::cout << "It's me." << std::endl; });
runJobFromPool();
return 0;
}
不幸的是,您不会看到完美的调用堆栈。但是你可以from_here
在调试器中看到。
void lambda_1a7009ccf8810b62b59083b4c1779e56() 0x345678920
void lambda_a7009ccf8810b62b59083b4c1779e569() 0x345678910 <-- Here `from_here` will be available: "main"
void runJobFromPool() 0x234567890
int main(int, char**) 0x123456780
推荐阅读
- apache-kafka - 如果我们通过 Apache Kafka 设置 RDBMS 复制,FK(外键)会出现问题吗?
- python - 使用 pandas 中的查询函数返回位于两个列表交集处的行
- parsing - 程序错误:未定义成员:>>= Haskell
- mp4 - H.264 MP4 文件中存储的像素格式在哪里?
- javascript - 如何更改一个ajax函数的字体大小
- python-3.x - PyTorch 中的 nn.functional() 与 nn.sequential() 之间是否存在计算效率差异
- json - 通过 GET https://api.groovehq.com/v1/tickets 打印数据
- bash - 暂停 bash 脚本,直到另一个脚本发出信号
- angular - 为具有相似结构的需求创建方法或服务
- amazon-web-services - (以编程方式)推断部署 AWS 模板所需的 AWS IAM 权限