2013-12-19 3 views
6

Я создаю детектор утечки памяти для C++. Он заменяет глобальный новый оператор и использует макрос инициализирует две глобальные переменные, __file__ и __line__, например, так:redefine __LINE__ и __FILE__ константы

#define new (__file__=__FILE__,__line__=__LINE__) && 0 ? NULL : new 

Я узнал этот трюк от другого пользователя StackOverflow, чье имя я не могу вспомнить. Это отлично работает с простыми операциями, связанными с новыми, однако эта оценка вызывает проблему, когда пользователь определяет локальный оператор, новый для пространства имен. Во-первых, линии, подобные

void* operator new(size_t size); 

также соответствует макро; также, явные призывы к глобальным новым, например:

int* i = ::new int; 

вызывает синтаксические ошибки.

Есть ли способ переопределить или подавить константы __LINE__ и __FILE__ (чтобы они отображали имя файла и номер строки вызова оператора new) в части кода? Если нет, как можно улучшить макрос, чтобы не соответствовать пользовательскому «оператору нового» и не вызвать проблему с «:: new»?

Я бы очень хотел избавиться от неудобства макросов. Заранее спасибо :)

+2

Именно поэтому определение языка C++ не позволяет создавать макросы, которые переопределяют ключевые слова. –

+0

Назначение новых значений двум глобальным переменным (что, чтобы усугубить использование зарезервированных имен) путем переопределения ключевого слова не будет делать детектор утечки, хотя (если вы не предполагаете, что это всегда последнее утечка). Хотя вы уже используете нестандартные вещи, я бы предпочел вам перегружать глобальные 'operator new' и' delete' с помощью специального распределителя, который запоминает '__builtin_return_address (1)' для каждого распределения. – Damon

+0

@Damon Макрос - это не единственная часть программы, я заменил глобальные новые и удаленные операторы. Информация хранится в связанном списке. – user3109672

ответ

0

Хорошо, я отказался от попытки сделать работу макроса. По внешнему виду это не может. Я написал скрипт perl, чтобы выполнить эту работу. Он выполняется перед предварительной обработкой (предварительный препроцессор), и он делает более разумную замену, чем то, что сделает препроцессор C. Эти регулярные выражения используются для соответствия нового и новый :: в чем-то еще:

$this =~ s/(::)?\s*new([^\w_])/__fl_init(__FILE__,__LINE__)?NULL: $1new$2/g; 

Я не знаю, может быть, я буду писать пакетный файл для автоматической предварительной предобработки источника. Пожалуйста, сделайте комментарий, если кто-то знает обход, используя CPP.

+0

Рад слышать, что вы отказались от усилий, потому что создание макросов, которые переопределяют ключевые слова языка, должно быть уголовным преступлением, что отражается в том, что стандарт C++ запрещает его. –

0

Я не знаю, как это сделать без инстинктов. Раньше я использовал средство замены регулярных выражений или C++ (например, инструменты рефакторинга, доступные в Visual Studio), чтобы изменить все экземпляры new, чтобы явно вызвать макрос, который записывает номер файла и строки.

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

Редактировать: Для вашего конкретного случая вы можете просто определить макрос и переопределить его после экземпляров идентификатора new, вызывающего проблемы.

+0

слишком плохо Я разрабатываю это приложение для платформы, на которой нет ни окон, ни библиотеки Linux.Также мне нужно отслеживать вызовы на глобальные новые, поэтому, вероятно, небезопасно игнорировать эти строки. – user3109672

Смежные вопросы