Форум программистов, компьютерный форум CyberForum.ru

C++

Войти
Регистрация
Восстановить пароль
 
karat39
4 / 4 / 1
Регистрация: 09.02.2016
Сообщений: 74
#1

Освобождение памяти после std:bind - C++

01.08.2016, 13:49. Просмотров 326. Ответов 11
Метки нет (Все метки)

Что имею:
- CentOS
- gcc 4.8
- valgrind

Что делаю
- С помощью valgrind устраняю утечки
- Если приложение остановлено штатно, то все утечки я устранил
- Если останавливаю с помощью ctrl-c, valgrind рапортует об куче неосвобожденной памяти. Скорее всего, нужно в деструкторах освободить руками.

Проблема
Получаю такой кусок отчета

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
24 bytes in 1 blocks are still reachable in loss record 2 of 6
at 0x4C2A105: operator new(unsigned long) (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
 
by 0x402FDC: _M_clone (functional:1910)
 
by 0x402FDC: std::_Function_base::_Base_manager<std::[B]_Bind[/B]<std::_Mem_fn<void (MyClassWorker::*)(header_struct*, void*, bool)> (MyClassWorker*, std::_Placeholder<1>, std::_Placeholder<2>, std::_Placeholder<3>)> >::_M_manager(std::_Any_data&, std::_Any_data const&, std::_Manager_operation) (functional:1946)
 
by 0x404D3F: function (functional:2442)
 
by 0x404D3F: operator= (functional:2275)
 
by 0x404D3F: MyClass::MyClass(char const*, char const*, unsigned int, char const*, unsigned int, unsigned int, char const*, [B]std::function<void (header_struct*, void*, bool)[/B]>) (MyClass.cpp:49)
 
by 0x4026DD: main (main.cpp:26)
Делаю вывод, что выделение памяти вызвано созданием функции bind (хотя пока писал, быть может память выделилась под ее переменные). Следовательно вопрос, как то можно ее освободить в конструкторе?
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
DrOffset
6840 / 4051 / 924
Регистрация: 30.01.2014
Сообщений: 6,855
01.08.2016, 15:39     Освобождение памяти после std:bind #2
Цитата Сообщение от karat39 Посмотреть сообщение
Следовательно вопрос, как то можно ее освободить
Не-не, не все так просто. Оставь пока bind в покое. Ты наблюдаешь симптом, а лечить надо причину.

Проблема где-то в твоем коде, не видя которого, будет очень сложно тебе помочь.

Добавлено через 2 минуты
Цитата Сообщение от karat39 Посмотреть сообщение
Если останавливаю с помощью ctrl-c
При всем при этом, обработка ctrl-c должна быть корректной. В том смысле, что приложение должно быть готово к обработке этого сигнала.
Хоть что-то было сделано в этом направлении?
karat39
4 / 4 / 1
Регистрация: 09.02.2016
Сообщений: 74
01.08.2016, 16:10  [ТС]     Освобождение памяти после std:bind #3
Цитата Сообщение от DrOffset Посмотреть сообщение
В том смысле, что приложение должно быть готово к обработке этого сигнала.
Хоть что-то было сделано в этом направлении?
да, начал сразу же копать в этом направлении. Понял, что нужно обрабатывать руками. Выкрутился через
C++
1
signal(SIGINT, <func>)
В принципе, теперь все стало корректно закрываться, valgrind теперь больше не ругается. Утечки/некорректное использование все устранены.

Еще бы придумать, как простой kill или kill -9 перехватывать и вызывать конструкторы, но я так понимаю не судьба.

Добавлено через 8 минут
В принципе на это тоже есть ответ.
C++
1
signal(SIGTERM, <func>)
Но тогда есть риск получить постоянно зацикленное приложение без возможности вырубания. Если только пройти все циклы руками и вставить проверку на сигнал.
DrOffset
6840 / 4051 / 924
Регистрация: 30.01.2014
Сообщений: 6,855
01.08.2016, 19:16     Освобождение памяти после std:bind #4
Цитата Сообщение от karat39 Посмотреть сообщение
<func>
Есть подозрение, что и сейчас у тебя тоже не совсем правильно сделано.

Дело в том, что в функции-обработчики имеют довольно сильные ограничения на свое содержимое. На самом деле внутри них можно делать достаточно мало чего. Например очень плохо, если обработчик занимается выделением или освобождением памяти. Список функций, которые можно из них вызывать есть в мане. Если, например, из обработчика нужно дергать общую с остальным приложением переменную, то она должна быть типа sigatomic_t.

Поэтому более правильным будет либо использовать функции sigwait\sigtimedwait и выполнять ожидание в отдельном для сигналов потоке (пример есть тут), либо использовать события на signalfd (ожидание через poll/select и т.п.) пример есть тут. Оба способа позволяют обрабатывать сигнал в "нормальном" режиме, без ограничений на выполняемые операции. Какой из способов лучше - зависит от архитектуры приложения.
karat39
4 / 4 / 1
Регистрация: 09.02.2016
Сообщений: 74
01.08.2016, 19:29  [ТС]     Освобождение памяти после std:bind #5
Цитата Сообщение от DrOffset Посмотреть сообщение
Дело в том, что в функции-обработчики имеют довольно сильные ограничения на свое содержимое
У меня все очень предельно просто реализовано. Думаю не должно быть проблем. За маны спасибо, вникать я люблю.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
bool is_exit = false;
 
void signal_func(int _signal) {
    if (_signal != SIGINT) return;
    is_exit = true;
}
 
int main()
{
    signal(SIGINT, signal_func);
    while (true) {
        ...
        ...
        ...
        if (is_exit) break;
    }
}
DrOffset
6840 / 4051 / 924
Регистрация: 30.01.2014
Сообщений: 6,855
01.08.2016, 19:32     Освобождение памяти после std:bind #6
Цитата Сообщение от karat39 Посмотреть сообщение
Думаю не должно быть проблем.
bool на sigatomic_t замени.
karat39
4 / 4 / 1
Регистрация: 09.02.2016
Сообщений: 74
01.08.2016, 19:34  [ТС]     Освобождение памяти после std:bind #7
Цитата Сообщение от DrOffset Посмотреть сообщение
ожидание в отдельном для сигналов потоке (пример есть тут)
с этим пока заминка. Задача пока стоит реализовать рабочие алгоритмы в одном потоке.
Реализовать, оттестить и запустить в эксплуатацию. Потом после ходовых испытаний начать распараллеливать. Пока на это табу. Поэтому принципиально не запускаю потоки.

Добавлено через 2 минуты
Цитата Сообщение от DrOffset Посмотреть сообщение
bool на sigatomic_t замени
спасибо.
DrOffset
6840 / 4051 / 924
Регистрация: 30.01.2014
Сообщений: 6,855
01.08.2016, 19:38     Освобождение памяти после std:bind #8
Цитата Сообщение от karat39 Посмотреть сообщение
Задача пока стоит реализовать рабочие алгоритмы в одном потоке.
Безотносительно этих твоих требований скажу, что этот поток не должен заниматься никакой работой, кроме ожидания сигнала.
Например, в основном (и единственном рабочем) потоке можно сделать очередь событий, в которую помимо насущных задач, иногда будут поступать события, сгенерированные по приходу сигналов из второго потока. В этом смысле у нас второй поток не занимается работой, он только изредка просыпается, если пришел сигнал, и ставит в очередь событие. Важно, чтобы это было понятно. И использовать или не использовать эту технику решалось исходя из архитектуры, а не категоричного запрета на потоки
karat39
4 / 4 / 1
Регистрация: 09.02.2016
Сообщений: 74
02.08.2016, 11:13  [ТС]     Освобождение памяти после std:bind #9
Цитата Сообщение от DrOffset Посмотреть сообщение
bool на sigatomic_t замени
изучил более подробно маны и этот момент, спасибо, дельный был совет.

Цитата Сообщение от DrOffset Посмотреть сообщение
потоке можно сделать очередь событий, в которую помимо насущных задач, иногда будут поступать события .... В этом смысле у нас второй поток не занимается работой, он только изредка просыпается, если пришел сигнал, и ставит в очередь событие
я понимаю, что моя просьба уже будет за пределами темы топика. Не могли бы вы куда нибудь меня отправить изучить/почитать по данной тематике. То что вы описали - это предмет моей будущей задачи. Я пока плавно готовлюсь к ней. Почитываю пока Уильямса "Параллельное программирование в c++". Вы очень четко сформулировали, то что мне надо. Очередь событий, пул потоков, пробуждения, засыпания и тд.
Заранее спасибо.
DrOffset
6840 / 4051 / 924
Регистрация: 30.01.2014
Сообщений: 6,855
02.08.2016, 15:53     Освобождение памяти после std:bind #10
Цитата Сообщение от karat39 Посмотреть сообщение
Почитываю пока Уильямса "Параллельное программирование в c++"
По многопоточности можно еще почитать The Art of Multiprocessor Programming. По системным вызовам Linux рекомендую книгу The Linux Programming Interface.

Насчет того, что я выше описал, где-то у меня лежал небольшой пример на эту тему (писался тоже для какой-то демонстрации). Если надо - могу поискать.
karat39
4 / 4 / 1
Регистрация: 09.02.2016
Сообщений: 74
02.08.2016, 17:55  [ТС]     Освобождение памяти после std:bind #11
Цитата Сообщение от DrOffset Посмотреть сообщение
Насчет того, что я выше описал, где-то у меня лежал небольшой пример на эту тему (писался тоже для какой-то демонстрации). Если надо - могу поискать.
был бы признателен.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
03.08.2016, 22:25     Освобождение памяти после std:bind
Еще ссылки по теме:

Error: cannot bind 'std::basic_ostream<wchar_t>' lvalue to 'std::basic_ostream<wchar_t>&&'| C++
C++ Проверить объект в std::bind на живучесть
C++ Разобраться с std::bind, плейсхолдеры
C++ Освобождение памяти
Правильное освобождение памяти при std::vector C++

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
Dmitriy_M
1334 / 1215 / 110
Регистрация: 20.03.2009
Сообщений: 4,338
Записей в блоге: 11
03.08.2016, 22:25     Освобождение памяти после std:bind #12
На тему сигналов и потоков есть неплохая статья Доступ к разделяемым атомарным объектам из обработчика сигнала в C
Yandex
Объявления
03.08.2016, 22:25     Освобождение памяти после std:bind
Ответ Создать тему
Опции темы

Текущее время: 14:43. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru