Я работаю над небольшим инструментом памяти, который отслеживает распределение и освобождение, размеры объектов, типы объектов и так далее.Метод, который я использую для отслеживания исходных файлов, номеров строк и типов объектов, работает следующим образом:
#define DEBUG_NEW SourcePacket(__FILE__, __LINE__) * new
#define new DEBUG_NEW
SourcePacket - это просто небольшой класс, который принимает const char * и int во время построения.Эти значения заполняются с помощью макросов __FILE__
и __LINE__
.Тип объекта получается следующим образом:
template<typename T>
T* operator*(const SourcePacket& packet, T* p);
p - указатель на вновь выделенный объект, тип которого обнаружен с использованием RTTI.При перегрузке оператора информация берется и сохраняется в трассировщике, а указатель передается программе.Дополнительная информация, такая как размер и адрес, указана в перегруженном операторе new.
Теперь эта настройка очень хорошо работает для меня.Он не работает для кода, который я не компилирую, естественно, но одна из лучших вещей - это то, что он хорошо работает с размещением новых вызовов, сделанных пользователем, которые не работали с использованием часто встречающихся
#define new new(__FILE__, __LINE__)
метод.Проблема, с которой я столкнулся, заключается в том, что если пользователь вызывает оператор new, программа просто не сможет скомпилироваться.Конечно, это потому, что макрос расширяется примерно так:
return operator SourcePacket("blahblah.cpp", 20) * new(size);
вместо
return SourcePacket("blahblah.cpp", 20) * new(size);
Я действительно не вижу никакого способа обойти это.Я мог бы, конечно, просто удалить новую процедуру SourcePacket * и просто позволить моему перегруженному оператору new собирать размер и адрес, но это побеждает большую часть назначения инструмента.
(Также, как примечание, я не пытаюсь создать Valgrind или что-то еще, и я знаю, что перегрузка глобальных операций может быть довольно хитрой. Это в основном для образовательных целей. Кроме того, я знаю,что специфичные для ОС функции могут быть использованы для обнаружения некоторой этой информации, но я бы хотел использовать стандарт C ++ только для того, чтобы он был кроссплатформенным и бит-независимым (x86, x64 и т. д.). Пока это работаетбезупречно для меня как в Linux, так и в Windows, выпусках обоих версий.)
К сожалению, нет никакого способа условно использовать тот или иной путь, в зависимости от того, является ли он просто новым (илиразмещение нового) или оператора нового.Не критично, что я заставлю это работать, но мне было бы интересно узнать, нашел ли кто-нибудь способ обойти это ограничение.