Есть ли какой-либо способ убедиться, что моя функция будет последней вызываемой функцией?

#c #memory-leaks

#c #утечки памяти

Вопрос:

Я переопределил глобальную new/delete , чтобы зафиксировать утечку памяти. Когда процесс завершается, мне нужно вызвать assertNoMemoryLeak , чтобы подтвердить, что вся выделенная память с помощью new была освобождена.

Но, похоже, я не могу сделать так, чтобы assertNoMemoryLeak функция вызывалась последней в моем процессе, потому что деструктор некоторой глобальной переменной будет последним.

  1. atexit не работает по следующей причине. AFAIK, глобальный деструктор, сгенерированный gcc, будет помещен в atexit список при вызове конструктора, и я также не могу запустить свой фрагмент push ‘assertNoMemoryLeak’ до этого во время запуска, поэтому моя assertNoMemoryLeak функция все равно не будет запускаться последней.

  2. Другой обходной путь — записать new/delete информацию в файл, а затем после завершения процесса проанализировать файл (используя скрипт). Я не хочу делать это таким образом, потому что сложно автоматически выполнять это для каждого разработчика.

Итак, есть какой-нибудь способ сделать assertNoMemoryLeak последнюю вызываемую функцию?

Комментарии:

1. Я удалил тег C , поскольку этот вопрос явно не о C.

2. Не ответ, но почему бы вместо этого не использовать Valgrind для обнаружения утечек памяти ?

3. Если у вас есть только одна единица преобразования, вы можете создать глобальный объект, который создается перед любым другим глобальным объектом, и вызвать его atexit() в конструкторе, и в этом случае стандарт гарантирует, что зарегистрированная функция не будет вызвана до тех пор, пока все глобальные объекты не будут уничтожены. Однако с несколькими единицами перевода вам не повезло.

4. Однако, если вы используете GCC, вы можете использовать init_priority атрибут , чтобы принудительно инициализировать ваш atexit регистрирующий объект первым, но для этого требуется поддержка компоновщика , поэтому это может не сработать для Android.

5. @T.C.: «вызовите ее atexit() в конструкторе» — или, проще говоря, выполните работу в деструкторе.

Ответ №1:

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

Вы можете сделать это, заменив все глобальные статические объекты на указатели, или сделав их членами одного главного объекта, или переписав код без глобальных объектов. Суть в том, чтобы исключить все, что имеет запуск и завершение работы, которые вы не контролируете, затем запустить ваши проверки assert в нужное время в деструкторе этого одного глобального объекта, которым вы управляете.

Комментарии:

1. Если вы создаете глобальные указатели, вы можете избежать изменения другого кода, определив старое имя как ссылку на разыменованный указатель, предполагая, что главный объект запуска правильно инициализировал этот указатель, прежде чем какой-либо другой код его использует.