Я собираюсь удалить «как можно больше» динамического распределения кучи в моем приложении, и мне интересно, как я могу убедиться, что ничего не пропустил.
В настоящее время я ищу способлегко или даже автоматически определить, могут ли какие-либо (или какие) части кода вызывать стандартные реализации new
/ delete
или malloc
/ free
без необходимости динамического отслеживания выделений (т. е. с помощью статического анализа кода)или обратная связь от компилятора / компоновщика).
Легко обнаружить (или найти) код, который напрямую вызывает new
или malloc
, конечно:
int main() {
auto s = new std::string();
delete s;
}
На всякий случайвыделения скрыты глубоко в сторонней библиотеке или в случаях, которые менее очевидны (например, throw
), я все еще могу искать искаженные символы для нового / удаления в моем двоичном файле:
g++ main.cpp
nm a.out | grep -E "_Znwm|_Znam|_Znwj|_Znaj|_ZdlPv|_ZdaPv|malloc|free"
U _ZdlPvm@@CXXABI_1.3.9
U _Znwm@@GLIBCXX_3.4
Но этот подходбудет только прямой использования new/delete/malloc/free
.В случае, если мой код (или материал сторонних производителей) использует стандартную библиотеку, вы не обнаружите ее, просто позвонив по номеру nm
:
int main() {
std::string a;
for(int i = 0; i < 100; ++i) {
a += "data ";
}
}
Мой текущий подход заключается в связывании со статическими стандартными библиотеками (-static-libgcc
/ -static-libstdc++
) и посмотрите, есть ли ссылка на new
/ delete
на всех во всем двоичном файле:
g++ -static-libgcc -static-libstdc++ main.cpp
nm a.out | grep -E "_Znwm|_Znam|_Znwj|_Znaj|_ZdlPv|_ZdaPv|malloc|free"
0000000000471fd0 T __cxa_free_dependent_exception
0000000000471f30 T __cxa_free_exception
U free@@GLIBC_2.2.5
U __freelocale@@GLIBC_2.2.5
U malloc@@GLIBC_2.2.5
0000000000471b20 T _ZdlPv
0000000000491bf0 T _ZdlPvm
0000000000471bc0 t _ZN12_GLOBAL__N_14pool4freeEPv.constprop.2
0000000000402a20 t _ZN12_GLOBAL__N_14pool4freeEPv.constprop.2.cold.5
0000000000471e80 T _ZN9__gnu_cxx9__freeresEv
0000000000472240 T _Znwm
0000000000491c00 T _ZnwmRKSt9nothrow_t
0000000000403f37 t _ZnwmRKSt9nothrow_t.cold.0
Этот подход работает для небольших двоичных файлов, гдевы можете иметь ноль распределений кучи, но как только вы захотите разрешить некоторые выделения (например, в коде, который выполняется только один раз, или в случаях ошибок, становится очень трудно, следовательно, разделитькод, который может выделить память кучи, а материал, который не будет.
В лучшем случае, я могу себе представить, что компилятор или статический анализатор кода предоставляет мне список мест в моемисходный код, который может привести к динамическому выделению кучи. Этот список я мог регулярно проверять / фильтровать для случаев, которые в моей настройке хороши (например, загрузочный код или обработка ошибок), и те,где я должен провести рефакторинг (например, предоставив специальный распределитель).
Каковы ваши подходы, инструменты, опыт?