#cpp
Имеется больше тысячи cpp файлов, необходимо в текстовом файле вывести список всех глобальных переменных. Есть ли специальный софт для решения подобной задачи? Или необходимо писать свой скрипт?
Ответы
Ответ 1
Вот, поподробнее об использовании nm (см. man nm) для получения списка глобальных переменных, определенных в заданных .cpp файлах. Я подразумеваю, что интересны только переменные (и константы), но не функции. Для примера сделаем пару С++ файлов. // ext1.cpp #includeusing namespace std; int esum, e1 = 1; extern int e2; int const econ1 = 2; // в c++ это НЕ ГЛОБАЛЬНАЯ КОНСТАНТА !!! extern int const econ; // а это ГЛОБАЛЬНАЯ(!!!), но не определенная здесь void sumext(); int main () { sumext(); // помещает сумму всех глобальных (кроме esum) в esum cout << "DoubleSum: " << esum + econ + e1 + e2 << '\n'; } // ext2.cpp extern int esum, e1; int e2 = 2; extern int const econ = 3; // ГЛОБАЛЬНАЯ КОНСТАНТА, определена здесь void sumext() { esum = e1 + e2 + econ; } Оттранслируем их, получив объектные файлы ext1.o и ext2.o avp@avp-ubu1:~/hashcode$ g++ -c ext1.cpp ext2.cpp и посмотрим на вывод утилиты nm avp@avp-ubu1:~/hashcode$ nm ext[12].o ext1.o: 000000000000009f t _GLOBAL__sub_I_esum 000000000000005f t _Z41__static_initialization_and_destruction_0ii U _Z6sumextv 000000000000000c r _ZL5econ1 U _ZNSolsEi U _ZNSt8ios_base4InitC1Ev U _ZNSt8ios_base4InitD1Ev U _ZSt4cout 0000000000000004 b _ZStL8__ioinit U _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc U _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_c U __cxa_atexit U __dso_handle 0000000000000000 D e1 U e2 U econ 0000000000000000 B esum 0000000000000000 T main ext2.o: 0000000000000000 T _Z6sumextv U e1 0000000000000000 D e2 0000000000000000 R econ U esum Легко заметить, что инициализированные переменные e1 и e2 отмечены флагом D, неинециализированная переменная esum отмечена флагом B, а глобальная константа флагом R. В файлах, где эти переменные и константа являются внешними, они отмечены флагом U. Для первого приближения к решению можно написать скрипт на awk avp@avp-ubu1:~/hashcode$ for i in ext[12].o; do echo Global variables defined in $i; nm $i | awk 'NF == 3 && ($2 == "D" || $2 == "B" || $2 == "R") { print $2 " " $3 }'; done Global variables defined in ext1.o D e1 B esum Global variables defined in ext2.o D e2 R econ Ну и наконец, сделать исполнимый модуль и посмотреть, работает ли программа avp@avp-ubu1:~/hashcode$ g++ -o ext12 ext1.o ext2.o avp@avp-ubu1:~/hashcode$ ./ext12 DoubleSum: 12 avp@avp-ubu1:~/hashcode$ Ответ 2
Вначале берем ctags либо cscope (в линукс дистрибутивах есть в репозитариях) и натравливаем на исходники. На выходе получаем специальный tag файл, в котором собрана информация о всех переменных, функциях и тому подобное. А дальше либо учиться разбирать формат tag файла, либо воспользоваться встроенными средствами.Ответ 3
Не надейтесь вручную найти все глобальные переменные, анализируя исходный код: синтаксис C++ безнадёжно сложен для того, чтобы написать сколько-нибудь подходящий парсер за короткое время. Вам нужно воспользоваться существующим парсером. На SO рекомендуют попросить компилятор (который уж точно знает, как распарсить ваш проект) создать map-файл. Вот как его включить в gcc: http://gcc.gnu.org/onlinedocs/gcc/Link-Options.html. У меня map-файл сгенерировался следующим вызовом: g++ -Wl,-Map,maptest.map maptest.cpp В нём довольно много лишнего, так что вам, если вы пойдёте этим путём, придётся разобраться, как этот самый map-файл читать. Насколько я понимаю, вам нужна секция .bss, исключая переменные из модулей, лежащих в /usr/lib. В MSVC можно тоже включить map-файл через опции компоновщика (/MAP или Project properties -> Linker -> Debugging -> Generate map file), тут тоже придётся научиться разбирать файл (хотя субъективно выглядит проще), ищите данные из своих объектных модулей, не отмеченных как функция (буква f в одной из колонок). Попробовал идею @avp с nm, она гораздо лучше. Разберитесь в том, что такое объектный файл, и используйте её. Для MSVC есть аналогичная утилита dumpbin.
Комментариев нет:
Отправить комментарий