Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / C++ Новый топик    Ответить
 Профилирующая обертка для new  [new]
EvLaUy
Member

Откуда: Москва
Сообщений: 2163
Решаю задачу профилирования выделения и освобождения памяти для крупного программного проекта с большим количеством файлов исходного кода. По работе с памятью проект написан в смешанном стиле, используется средства как C, так и C++. Для функций malloc, calloc, realloc и free сделал обертки примерно в таком стиле. Возьмем для примера malloc.
Вхождения вида ptr=malloc(size)
заменил на вызов собственной функции
ptr=wrapper_malloc("path_to_this_source_file", __FUNCTION__, __LINE__, size)
а в этом раппере выделяю память стандартным malloc и печатаю в специальный файл всю сопроводительную информацию,
переданную в аргументах, а также значение выделенного адреса в 16-ричном виде. Результат malloc в конце возвращаю.
Остальные рапперы построены по тому же принципу с учетом конкретики других функций.
Это работает.
Но как быть с профилированием new? С-функции однотипны, а new всякий раз работает с конструкторами разных классов, у каждого из этих конструкторов свои аргументы. Не хочется каждый new оборачивать по отдельности, это очень долго и трудоемко. Можно ли предложить для new тоже какое-то более и ли менее общее решение, позволяющее профилировать такую информацию (плюс печать еще и имени типа/класса)? Я знаю, что оператор new можно перезагружать (написать свою реализацию), но сам я ни разу еще этого не делал, да и поможет ли здесь такое решение? Тот же вопрос и для delete. Заранее спасибо гуру C++ за консультацию.
12 сен 18, 11:16    [21671859]     Ответить | Цитировать Сообщить модератору
 Re: Профилирующая обертка для new  [new]
Cerebrum
Member

Откуда: Омикрон Персей 8
Сообщений: 7704
Если смысл всей этой кухни только ради того, чтобы отслеживать утечки памяти, то для Windows есть стандартное решение

работает для new/delete и malloc/free, поддерживается отслеживание утечек в разных потоках общего процесса
+
если кратко, то берутся две точки программы, например, в начале функции main и перед выходом из нее в return. Анализируется heap и если остались неосвобожденными какие-либо объекты IDE выводит их перечень с указаниями размеров разлитой памяти и, если возможно, местом дислокации выделения этой памяти в коде.

к сожалению, оно не поможет отслеживать вам утечки COM объектов
RAII наше все!
12 сен 18, 11:29    [21671878]     Ответить | Цитировать Сообщить модератору
 Re: Профилирующая обертка для new  [new]
EvLaUy
Member

Откуда: Москва
Сообщений: 2163
Cerebrum,
спасибо за ответ. Нет, задача состоит не в поиске утечек. Все утечки давно выявлены и устранены. Речь идет именно о профилировании: построить статистику выделения памяти по конкретным местам, размерам, времени жизни выделенной памяти. На основании собранной информации и анализа данных предложить где и какие кастомные аллокаторы можно использовать для
экономии памяти. По кастомным аллокаторам есть множество теоретических работ - где, когда, какие и в каких случаях, не буду сейчас вдаваться, т.к. вопрос не в этом. Тут важно профилировать именно ту информацию, о которой я написал.
12 сен 18, 11:33    [21671884]     Ответить | Цитировать Сообщить модератору
 Re: Профилирующая обертка для new  [new]
rdb_dev
Member

Откуда: с болот
Сообщений: 2363
EvLaUy, оператор new в классах всегда один и тот же:
void* ClassName::operator new (size_t) throw(bad_alloc);
void* ClassName::operator new[] (size_t) throw(bad_alloc);
12 сен 18, 11:34    [21671887]     Ответить | Цитировать Сообщить модератору
 Re: Профилирующая обертка для new  [new]
EvLaUy
Member

Откуда: Москва
Сообщений: 2163
rdb_dev,
да, конечно, это так. Я прошу практического совета или подсказки, в какую сторону смотреть.
Вот у меня две строчки кода:
A a = new A(C, D);

B b = new B(E, F);

Можно ли построить какую-то более или менее общую обертку, которая во-первых:
1) выполняла бы в каждом случае заказанную работу, т.е. выделяла бы память под инстанс данного класса, передавая в конструктор
нужные аргументы
2) записывала в лог-файл сопроводительную информацию, включая имя класса, для которого создан инстанс

Я могу написать для первого случая
A a = wrapper_newA_twoargs("filename", "A", __FUNCTION__, __LINE__, C,D)
B b = wrapper_newB_twoargs("filename", "B", __FUNCTION__, __LINE__, E,F)

но это же не дело - для каждого конструктора каждого класса писать свой wrapper, тогда проще уж прямо в коде рядом
с вызовом new делать запись в лог. Существует ли более или менее общее решение (с помощью перезагрузки new или с помощью
шаблонов), которое позволило бы и для A, и для B делать какой-то однотипный вызов?
12 сен 18, 11:48    [21671911]     Ответить | Цитировать Сообщить модератору
 Re: Профилирующая обертка для new  [new]
rdb_dev
Member

Откуда: с болот
Сообщений: 2363
Просто переопредели
void* operator new(size_t sz) throw(bad_alloc)
{
  register void* ptr = std::malloc(sz);
  if (NULL == ptr)
  {
    my::writeLog(sz);
    throw bad_alloc();
  }
  my::writeLog(sz);
  return ptr;
}
12 сен 18, 11:56    [21671925]     Ответить | Цитировать Сообщить модератору
 Re: Профилирующая обертка для new  [new]
EvLaUy
Member

Откуда: Москва
Сообщений: 2163
rdb_dev,
да, это понятно. Но так я смогу логировать только размер выделенной памяти и само значение выделенного адреса, но не информацию о том, из какого места исходного кода была запрошена память, и имя класса/структуры (если память выделена
не для данных простого типа).
12 сен 18, 12:02    [21671934]     Ответить | Цитировать Сообщить модератору
 Re: Профилирующая обертка для new  [new]
EvLaUy
Member

Откуда: Москва
Сообщений: 2163
Ладно, видимо мои вопросы от недостаточной грамотности. Я путаю вызов new и вызов конструктора класса, а это разные вещи, которые у меня в голове смешались. Не буду морочить специалистам голову, можно закрыть топик.
12 сен 18, 12:09    [21671941]     Ответить | Цитировать Сообщить модератору
 Re: Профилирующая обертка для new  [new]
Cerebrum
Member

Откуда: Омикрон Персей 8
Сообщений: 7704
EvLaUy
Ладно, видимо мои вопросы от недостаточной грамотности. Я путаю вызов new и вызов конструктора класса, а это разные вещи, которые у меня в голове смешались. Не буду морочить специалистам голову, можно закрыть топик.

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

то что вы хотите похоже на описание шаблона функтора с произвольным количеством передаваемых аргументов, на этот счет можно поковырять std::function или в сторону Александреску с его списками типов
12 сен 18, 12:27    [21671971]     Ответить | Цитировать Сообщить модератору
 Re: Профилирующая обертка для new  [new]
Dimitry Sibiryakov
Member

Откуда:
Сообщений: 45720

А почему бы просто не воспользоваться профилером? Он покажет всё, в том числе и вызовы
функций выделения памяти.

Posted via ActualForum NNTP Server 1.5

12 сен 18, 12:28    [21671974]     Ответить | Цитировать Сообщить модератору
 Re: Профилирующая обертка для new  [new]
EvLaUy
Member

Откуда: Москва
Сообщений: 2163
Хорошо, насчет закрыть я несколько погорячился. Пусть пока остается, я отпишусь, когда определюсь с решением.
12 сен 18, 12:28    [21671975]     Ответить | Цитировать Сообщить модератору
 Re: Профилирующая обертка для new  [new]
EvLaUy
Member

Откуда: Москва
Сообщений: 2163
Dimitry Sibiryakov,
да, покажет, но мне по каждому вызову нужна кастомная информация, которую профайлер обеспечить не может.
12 сен 18, 12:30    [21671977]     Ответить | Цитировать Сообщить модератору
 Re: Профилирующая обертка для new  [new]
clihlt
Member

Откуда: Донецк
Сообщений: 1119
EvLaUy,

Если хочется как смаллоком то
void* operator new(size_t sz,  char const * file, int line) throw(bad_alloc)
{
  register void* ptr = std::malloc(sz);
  if (NULL == ptr)
  {
    /// print file, line, size
    throw bad_alloc();
  }
  /// print file, line, size
  return ptr;
}

#define new new(__FILE__, __LINE__)


можно впринцыпе и коллстек напечатать
http://man7.org/linux/man-pages/man3/backtrace.3.html
12 сен 18, 12:32    [21671980]     Ответить | Цитировать Сообщить модератору
 Re: Профилирующая обертка для new  [new]
Dimitry Sibiryakov
Member

Откуда:
Сообщений: 45720

EvLaUy
мне по каждому вызову нужна кастомная информация

"По каждому"? Например?..

Posted via ActualForum NNTP Server 1.5

12 сен 18, 12:32    [21671981]     Ответить | Цитировать Сообщить модератору
 Re: Профилирующая обертка для new  [new]
EvLaUy
Member

Откуда: Москва
Сообщений: 2163
clihlt,

да, да, спасибо, мне что-то подобное тоже уже пришло в голову, но коллега cerebrum предложил посмотреть в сторону std::function и "высшего пилотажа" Александреску, отработаю еще и этот путь.
12 сен 18, 12:57    [21672016]     Ответить | Цитировать Сообщить модератору
 Re: Профилирующая обертка для new  [new]
clihlt
Member

Откуда: Донецк
Сообщений: 1119
EvLaUy,

https://en.wikipedia.org/wiki/KISS_principle
12 сен 18, 13:07    [21672038]     Ответить | Цитировать Сообщить модератору
 Re: Профилирующая обертка для new  [new]
Cerebrum
Member

Откуда: Омикрон Персей 8
Сообщений: 7704
мы легких путей не ищем Картинка с другого сайта.
12 сен 18, 13:08    [21672041]     Ответить | Цитировать Сообщить модератору
 Re: Профилирующая обертка для new  [new]
EvLaUy
Member

Откуда: Москва
Сообщений: 2163
Cerebrum,

"Ваше соединение не защищено

Владелец rsdn.org неправильно настроил свой веб-сайт. Чтобы защитить вашу информацию от кражи, Firefox не соединился с этим веб-сайтом."
Но про variadic templates не только на rsdn можно почитать.
12 сен 18, 13:36    [21672097]     Ответить | Цитировать Сообщить модератору
 Re: Профилирующая обертка для new  [new]
Cerebrum
Member

Откуда: Омикрон Персей 8
Сообщений: 7704
EvLaUy,

сижу на последнем firefox'e - никаких проблем с rsdn.ru нет

К сообщению приложен файл. Размер - 14Kb
12 сен 18, 13:39    [21672103]     Ответить | Цитировать Сообщить модератору
 Re: Профилирующая обертка для new  [new]
EvLaUy
Member

Откуда: Москва
Сообщений: 2163
Cerebrum,
верю. У меня из дома тоже нет. Но на работе, видимо, более сильные настройки безопасности.
12 сен 18, 13:54    [21672125]     Ответить | Цитировать Сообщить модератору
 Re: Профилирующая обертка для new  [new]
rdb_dev
Member

Откуда: с болот
Сообщений: 2363
EvLaUy
Cerebrum,
верю. У меня из дома тоже нет. Но на работе, видимо, более сильные настройки безопасности.
Видимо, у тебя на работе стоит антивирус с контролем всех HTTPS соединений, а у FireFox свой собственный контейнер сертификатов доверенных CA. Тебе надо вручную экспортировать сертификат локального доверенного CA антивируса из системного контейнера сертификатов и импортировать его в контейнер FireFox'а.
12 сен 18, 14:28    [21672214]     Ответить | Цитировать Сообщить модератору
 Re: Профилирующая обертка для new  [new]
miksoft
Member

Откуда:
Сообщений: 36929
EvLaUy,

http://rsdn.org/article/Variadic/VariadicTemplates.xml
А так?
12 сен 18, 14:48    [21672255]     Ответить | Цитировать Сообщить модератору
 Re: Профилирующая обертка для new  [new]
EvLaUy
Member

Откуда: Москва
Сообщений: 2163
miksoft,
так работает, спасибо.
12 сен 18, 17:16    [21672518]     Ответить | Цитировать Сообщить модератору
Все форумы / C++ Ответить