Учитывая стек вызовов, содержащий лямбда-функцию, как определить ее источник? - PullRequest
0 голосов
/ 17 мая 2018

Предположим, у вас есть какой-то код, который помещается в очередь, например так:

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() (игнорируя вставку). Впрочем, для лямбды ...

void lambda_a7009ccf8810b62b59083b4c1779e569() 0x345678901
void runJobFromPool()                          0x234567890
int main(int, char**)                          0x123456789

Это не так легко отладить. Если к этому подключен отладчик или доступен дамп ядра, то эту информацию можно использовать для определения того, какая лямбда-ошибка произошла, но эта информация не всегда доступна. Насколько я знаю, разборка - это один из немногих способов определить, что из этого получилось.

Идеи, которые я должен был сделать это лучше:

  1. Использование такого инструмента, как addr2line, если платформа поддерживает его. Это иногда работает, иногда нет.
  2. Завершение всех лямбд в функторах (по меньшей мере, не идеально).
  3. Не использовать лямбды (опять же, не идеально).
  4. Использование расширения компилятора для придания лямбде более значимого имени / добавления отладочной информации.

4-й вариант звучал многообещающе, поэтому я провел небольшое расследование, но ничего не смог найти. В случае, если это имеет значение, доступны следующие компиляторы: clang ++ 5.0 и MSVC 19 (Visual Studio 2015).

У меня вопрос, какие еще инструменты / методы доступны, которые могут помочь сопоставить стек вызовов с лямбда-функцией в нем с соответствующей строкой источника?

1 Ответ

0 голосов
/ 17 мая 2018

Боюсь, это невозможно.Вы должны разработать свою собственную технику хранения необходимой информации в лямдах.Ваш вариант 2 подходит здесь.Вы можете посмотреть, как это Google: 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...