найти вызывающего конструктора в C ++ - PullRequest
3 голосов
/ 04 февраля 2009

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

Знание того, откуда были вызваны ctor и dtor, поможет выявить проблему.

Тая \ 0

Ответы [ 12 ]

8 голосов
/ 04 февраля 2009

Если вы используете visual studio, вы можете подключить отладчик, и вместо точки останова использовать точку трассировки. Вы делаете это, щелкая правой кнопкой мыши точку останова и выбирая When Hit.... Затем выберите для печати сообщения, включая трассировку стека. Это сообщение будет отправлено на панель вывода, и вы сможете проанализировать все вызовы на досуге.

hit-point

6 голосов
/ 04 февраля 2009

Лучший способ, который я могу придумать, - это запустить вашу программу в отладчике и установить точку останова в конструкторе. Затем изучите стек вызовов.

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


Если вам нужно, чтобы стек вызовов был выгружен в журнал, я знаю, что можно создать дамп стека, используя, например, win32 API. Более общий подход состоял бы в том, чтобы сохранить явный стек вызовов как глобальное / специфичное для потока состояние, например, в std::vector<std::string> -объекте. (Используйте RAII, чтобы убедиться, что каждый push_back сопровождается pop_back)

3 голосов
/ 04 февраля 2009

Кажется, вы находитесь в Windows (OutputDebugString). Таким образом, вы можете использовать API StackWalk64 для получения трассировки стека. Подробнее см. Вопрос « Печать трассировки стека в C ++ (MSVC) ».

Существует также множество инструментов для обнаружения утечек (BoundsChecker и т. Д.).

2 голосов
/ 04 февраля 2009

Нет быстрого и грязного способа для этого, C ++ не предлагает никакого портативного способа просмотра трассировки стека. Если вы хотите искать утечки памяти, я бы порекомендовал посмотреть valgrind и подобные инструменты, они отлично справляются со своей задачей. В качестве руководства по кодированию, во-первых, избегайте утечек памяти с помощью RAII (всегда есть владелец ресурса).

1 голос
/ 04 февраля 2009

Если вы используете Linux, тогда Valgrind делает все, что вы хотите, и даже больше. Я считаю это необходимым при разработке на C ++.

1 голос
/ 04 февраля 2009

Используете gcc? Почему бы не создать трассировку стека ?

0 голосов
/ 04 февраля 2009

Спасибо всем за отзывы. установка точки останова в ctor невозможна из-за сотен вызовов новых объектов даже в течение короткого жизненного цикла программы.

Трассировка макросов в ctor и dtor сделала свое дело.

Визуальный детектор утечек и Stackwalk64 выглядят очень многообещающе

также найден AfxDumpStack (AFX_STACK_DUMP_TARGET_ODS); // OutputDebugString
но это ОЧЕНЬ шумно

0 голосов
/ 04 февраля 2009

Если вы используете g ++, вы можете построить свой проект для покрытия. Когда вы запускаете какой-то пример кода, вы можете просмотреть охват вашей программы, используя gcov .

Этот вывод включает в себя дерево вызовов, и вы должны видеть вызовы конструкторов и вызывающие их функции.

Единственный недостаток, о котором я могу подумать, это то, что вы получите вывод только для кода, который фактически выполняется, и поэтому вам понадобятся хорошие тестовые примеры. При этом выполнение анализа покрытия в любом случае того стоит. Наконец, я настоятельно рекомендую вам использовать lcov для просмотра результатов!

0 голосов
/ 04 февраля 2009

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

Знаете ли вы соглашение о вызовах , используемое для вашего конструктора? Если это так, вы можете использовать встроенный ассемблер (при условии, что ваш компилятор его поддерживает), чтобы проверить порядок вызовов функций. При вызове std, наиболее распространенном соглашении для Win32, извлечение стека покажет указатель на адрес, к которому необходимо вернуться после вызова функции (то есть в некотором месте в вызывающей функции). Это не идеально, но вы можете вернуться назад с этой точки, пока не достигнете адреса, который, как вы знаете, является началом функции. Единственная проблема здесь в том, что вам нужно получить адреса для всех ваших функций, чтобы сделать это ... это можно сделать с помощью простого трюка, чтобы получить значение eip в другом регистре прямо вверху функции. , затем переместив это значение в массив, который будет проверен позже при отладке, что-то вроде (синтаксис intel):

call label
label:
pop eax
mov [address of next array entry], eax
0 голосов
/ 04 февраля 2009

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

Смотрите эти ответы
Повреждение кучи под Win32; как найти?

Хороший замок.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...