devalone
@devalone
̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻

Куда утекает память?

Имеется класс Worker:
class Worker : public AbstractWorker {
public:
    Worker(Core* core, Module* module, WORKER_TYPE type = WORKER_TYPE::BEFORE_GRAPHICS, bool synchronized = false, const std::string& name = "");
    Worker(std::function<void(Worker*, unsigned)> function, Core* core, Module* module, WORKER_TYPE type = WORKER_TYPE::BEFORE_GRAPHICS, bool synchronized = false, const std::string& name = "");
    virtual ~Worker();

    virtual void handle(unsigned microseconds);

    WORKER_TYPE getType() const;

    bool isSynchronized() const;

protected:
    const WORKER_TYPE type;
    const bool synchronized;

private:
    std::function<void(Worker*, unsigned)> function;
};

Важным здесь является std::function<void(Worker*, unsigned)> function;, которая передаётся в конструкторе и вызывается из handle
void Worker::handle(unsigned microseconds)
{
    if (function)
        function(this, microseconds);
}

Сама функция handle вызывается из Core в цикле следующим образом:
while (_isAlive) {
        // TODO: убрать расход ресурсов на выделение памяти и прочее
        // parallel processing
        std::vector<std::future<void>> tasks;
        for (auto& worker : beforeGraphicsWorkers) {
            beforeGraphicsWorkersThreadPool->enqueue(
                [this, worker] {
                    auto now = getTimePoint();
                    auto dt = std::chrono::duration_cast<std::chrono::microseconds>(now - worker->previousHandlingTime).count();
                    worker->handle(dt);
                    worker->previousHandlingTime = now;
                });
        }

        // wait for threads finishing
        for (auto& task : tasks)
            task.wait();

// остальный код

    }

Если просто добавить лямбду, которая будет что-то делать, то всё ок, например так:
core.registerWorker(std::make_shared<Worker>([&core](auto worker, unsigned microseconds) {
        static int i = 0;
        i++;
    }, &core, nullptr));

registerWorker добавляет Worker в vector, который перебирается в функции обработки, приведённой выше. Но если же в Worker добавить вывод, то память стремительно уходит в небытие, например так:
core.registerWorker(std::make_shared<Worker>([&core](auto worker, unsigned microseconds) {
        static int i = 0;
        i++;
        std::cout << i << std::endl;
    }, &core, nullptr));

Если наследоваться от Worker и не использовать лямбды, тоже самое.
Что за магия? Может это как-то связано с тем, что Worker'ы постоянно вызываются из разных потоков?
Valgrind говорит, что так и должно быть -_-
==5048==
==5048== HEAP SUMMARY:
==5048== in use at exit: 0 bytes in 0 blocks
==5048== total heap usage: 1,851,012 allocs, 1,851,012 frees, 85,222,489 bytes allocated
==5048==
==5048== All heap blocks were freed -- no leaks are possible
==5048==
==5048== For counts of detected and suppressed errors, rerun with: -v
==5048== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
  • Вопрос задан
  • 347 просмотров
Пригласить эксперта
Ответы на вопрос 1
@koronabora
Человек
ИМХО:
1) Работающий вариант вырождается компилятором в ничегонеделание
static int i = 0;
i++;

2) Реальные действия спавнят на куче множество переменных, вот память и захватывается. Это не является утечкой.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы