Обнаружение утечек памяти в командной строке C / C ++ с использованием инструментов - PullRequest
2 голосов
/ 24 апреля 2020

Я пытаюсь обнаружить утечки памяти в C (и C ++) программах на macOS. В Linux и Windows я мог бы сделать это легко, используя valgrind, но, к сожалению, он недоступен в macOS.

Поскольку у меня есть опыт работы с Obj C и iOS dev, Я думал использовать инструменты для проверки утечки памяти. На первый взгляд, это звучало идеально для этой работы.

Я написал эту очень простую утечку программы:

#include <stdlib.h>
#include <stdio.h>

int* allocSomething() {
  return malloc(sizeof(int));
}

int main(int argc, const char * argv[]) {
  int* p = allocSomething();
  *p = 5;
  printf("*p = %d\n", *p);
  p = NULL;
  return 0;
}

Я запустил ее через Clang Stati c Analyzer которая выполнила эту работу, но я хотел, чтобы ее также нашли в инструментах, потому что я ищу подходящую замену Valgrind Таким образом:

  • Я изменил схему профиля, чтобы использовать Debug вместо Release.
  • Я убедился, что оптимизаций нет.

Однако после использования Инструменты: Instruments does not detect leaks

и, как вы можете видеть, утечки не зарегистрировано. После поиска в Интернете я обнаружил Не могу обнаружить C утечек в инструментах xcode 9 , в которых автор использовал sleep, поэтому я подумал, что, возможно, инструменты на самом деле не перекрывают malloc как Valgrind , но используйте технику сэмплирования, и она не сэмплирует ее в такой короткий срок, поэтому я изменил программу на:

int main(int argc, const char * argv[]) {
  int* p = allocSomething();
  p = NULL;
  sleep(600000);
  return 0;
}

Теперь я получаю: no leak at all

Что совершенно не имеет смысла, так как это очевидная утечка памяти. Я бы сказал, что это связано с оптимизацией, но потом я явно отключил это. Кроме того, если я malloc больше байтов, он обнаруживает это. Или, может быть, это ошибка в инструментах?

Так что мне интересно, если это проблема с инструментами, которые не могут обнаружить небольшие выделения? Должен отметить, что Вальгринд справляется с этим очень хорошо, поэтому я удивлен.

Есть ли у вас какие-либо предложения?

1 Ответ

2 голосов
/ 24 апреля 2020

Инструмент Leaks (один из инструментов в шаблоне Leaks) работает не так, как вы ожидаете.

Во-первых, почему он ничего не обнаруживает для краткосрочных процессов: он основан на таймере , Он останавливает процесс очень часто и проверяет его на утечки. Для недолговечного процесса проверка никогда не происходит до его завершения.

Во-вторых, почему он может пропустить некоторые утечки: он проверяет стеки всех потоков, регистры для всех потоков и ищет глобальные переменные. адреса распределений. Если адрес выделения найден в каком-либо из этих мест, это распределение не считается просочившимся.

В вашем случае адрес распределения, вероятно, все еще находится в регистре или в стековой памяти. В «реальной» программе стек и регистры в конечном итоге будут повторно использованы, и такие устаревшие данные будут удалены.

Инструмент распределения выделяет все распределения и освобождения (при условии, что процесс был запущен инструментами). Ваше утечка распределения находится в списке размещения и все еще перечислена как "живая" (также известная как Created & Persistent). Проблема заключается в том, что инструмент Allocations явно не вызывает такие распределения как утечки.

Кроме того, системные библиотеки также сделали выделения, которые предназначены для сохранения до завершения процесса и не очищаются явно. Итак, ваша утечка немного утопает в нерелевантной информации. Вы можете отфильтровать и отсортировать список распределения, чтобы выявить утечку, но это требует некоторых действий.

В контексте более реальной программы Instruments довольно хорошо обнаруживает утечки.

По-видимому, Clang поддерживает LeakSanitizer , как часть AddressSanitizer, так и автономно. Для этого может потребоваться более новая версия Clang, чем та, которую Apple поставляет в составе Xcode и / или Catalina. (Я тестировал с Xcode 11.3.1 на Mojave. Он не поддерживает опцию -fsanitize=leak, и ASAN_OPTIONS=detect_leaks=1 также не поддерживается.) Если предположить, что вы можете заставить это работать, это может вести себя больше, чем вы ожидаете .

...