Есть ли инструмент, который позволяет мне вставить одну строку кода во все функции и методы в C ++ - исходный файл? - PullRequest
2 голосов
/ 18 июля 2009

Это должно превратить это

int Yada (int yada)
{
   return yada;
}

в это

int Yada (int yada)
{
   SOME_HEIDEGGER_QUOTE;
   return yada;
}

но для всех (или, по крайней мере, большого количества) синтаксически допустимых конструкций функций и методов C / C ++.

Возможно, вы слышали о какой-то библиотеке Perl, которая позволит мне выполнять подобные операции в виде строк кода.

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

Ответы [ 6 ]

10 голосов
/ 18 июля 2009

Попробуйте Aspect C ++ ( www.aspectc.org ). Вы можете определить Аспект, который будет обрабатывать каждое выполнение метода.

На самом деле, быстрый старт в точности соответствует тому, что вы задали в качестве примера: http://www.aspectc.org/fileadmin/documentation/ac-quickref.pdf

5 голосов
/ 19 июля 2009

Я бы предложил использовать флаг gcc "- finstrument-functions" . По сути, он автоматически вызывает определенную функцию ("__cyg_profile_func_enter") при входе в каждую функцию, а другая функция вызывается ("__cyg_profile_func_exit") при выходе из функции. Каждой функции передается указатель на функцию, которая вводится / выходит, и функцию, которая вызвала эту функцию.

Вы можете выключить прибор для каждой функции или для каждого файла ... подробнее см. В документации.

Функция возвращается по крайней мере до версии 3.0.4 (с февраля 2002 г.).

Это предназначено для поддержки профилирования, но, похоже, не имеет побочных эффектов, как -pg (что компилирует код, подходящий для профилирования).

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

5 голосов
/ 19 июля 2009

Если вы строите с использованием GCC и флага -pg, GCC автоматически вызовет функцию mcount () в начале каждой функции. В этой функции вы можете проверить обратный адрес, чтобы выяснить, откуда вы были вызваны. Этот подход используется трассировщиком функции ядра Linux (CONFIG_FUNCTION_TRACER). Обратите внимание, что эта функция должна быть написана на ассемблере, и будьте осторожны, чтобы сохранить все регистры!

Кроме того, обратите внимание, что это должно быть передано только в фазе сборки, а не в связи, иначе GCC добавит библиотеки профилирования, которые обычно реализуют mcount.

2 голосов
/ 18 июля 2009

Нет такого инструмента, о котором я знаю. Чтобы распознать правильную точку вставки, инструмент должен включать полный синтаксический анализатор C ++ - для этого недостаточно регулярных выражений.

Но поскольку существует множество синтаксических анализаторов FOSS C ++, такой инструмент, безусловно, можно написать - своего рода интеллектуальный sed для кода C ++. Вероятно, самой большой проблемой будет разработка языка спецификаций для операции вставки / обновления / удаления - регулярные выражения, очевидно, не являются ответом, хотя они, безусловно, должны быть как-то включены в язык.

Люди всегда спрашивают здесь идеи для проектов - как насчет одного?

1 голос
/ 18 июля 2009

Я использую это регулярное выражение,

"(?<=[\\s:~])(\\w+)\\s*\\([\\w\\s,<>\\[\\].=&':/*]*?\\)\\s*(const)?\\s*{"

, чтобы найти функции и добавить дополнительные строки кода.

С помощью этого регулярного выражения я также получаю имя функции (группа 1) и аргументы (группа 2).
Примечание: вы должны отфильтровать имена как, "while", "do", "for", "switch".

0 голосов
/ 31 августа 2009

Это легко сделать с помощью системы преобразования программ.

DMS Software Reengineering Toolkit является системой преобразования программ общего назначения и может использоваться со многими языками (C #, COBOL, Java, EcmaScript, Fortran, ..), а также, в частности, с C ++.

DMS анализирует исходный код (используя полный язык интерфейса, в данном случае для C ++), создает абстрактные деревья синтаксиса и позволяет применять шаблоны от источника к источнику для преобразования кода из одной программы на C # в другую с любыми свойствами, которые вы пожелаете. Правило преобразования для точного выполнения указанной вами задачи:

domain CSharp.

insert_trace():function->function
  "\visibility \returntype \fnname(int \parametername)
   { \body  } "
       ->
  "\visibility \returntype \fnname(int \parametername)
   { Heidigger(\CppString\(\methodname\),
               \CppString\(\parametername\),
               \parametername);
      \body } "

Кавычки (") не являются кавычками C ++; скорее, они являются" доменными кавычками "и указывают, что содержимое внутри кавычек имеет синтаксис C ++ (потому что мы сказали" domain CSharp "). The \ foo нотации являются мета-синтаксисом.

Это правило соответствует AST, представляющему функцию, и переписывает это AST в отслеживаемую форму. Полученный AST затем печатается обратно в исходную форму, которую вы можете скомпилировать. Вам, вероятно, нужны другие правила для обработки других комбинаций аргументов; на самом деле, вы, вероятно, обобщите обработку аргументов, чтобы получить (где это возможно) строковое значение для каждого скалярного аргумента.

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

...