Есть ли способ определить во время выполнения, что исполняемый файл запускается из valgrind? У меня есть набор модульных тестов C++, и один из них ожидает, что std::vector::reserve выбросит std::bad_alloc. Когда я запускаю это под valgrind, он полностью выходит из строя, не позволяя мне тестировать как утечки памяти (с использованием valgrind), так и поведение (ожидая возникновения исключения).
Вот минимальный пример, который это воспроизводит:
#include <vector>
int main()
{
size_t uint_max = static_cast<size_t>(-1);
std::vector<char> v;
v.reserve(uint_max);
}
Запустив valgrind, я получаю следующий результат:
Warning: silly arg (-1) to __builtin_new()
new/new[] failed and should throw an exception, but Valgrind
cannot throw exceptions and so is aborting instead. Sorry.
at 0x40192BC: VALGRIND_PRINTF_BACKTRACE (valgrind.h:319)
by 0x401C823: operator new(unsigned) (vg_replace_malloc.c:164)
by 0x80487BF: std::vector<char, std::allocator<char> >::reserve(unsigned) new_allocator.h:92)
by 0x804874D: main (vg.cxx:6)
Я хотел бы изменить свой модульный тест, чтобы просто пропустить проблемный код, когда он запускается из valgrind. Это возможно?





Я посмотрел на документацию valgrind и не нашел легкого ответа. Но вот несколько вещей, которые вы можете попробовать:
Напишите свою собственную оболочку вокруг новой операции и вызовите исключение до того, как valgrind запустит свою новую частную функцию.
Попробуйте, как предложено выше, за исключением того, что вместо параметра командной строки (для которого требуется подключение) используйте переменную среды:
MYAPP_UNIT_TESTS_DISABLED = "NEW_MINUS_ONE,FLY_TO_MOON,DEREF_NULL" valgrind myapp
Тогда вы можете легко написать функцию
bool unit_test_enabled(const char *testname);
для защиты вашего модульного теста на основе значения, возвращаемого getenv (3).
Вы должны посмотреть на эта страница из руководства Valgrind, он содержит макрос RUNNING_ON_VALGRIND (включен в valgrind.h), который делает то, что вы хотите.
Если кто-то не хочет включать valgrind.h (для чего требуется тест autoconf или аналогичный) или использовать оболочку, вот эвристика для Linux (и других систем, использующих ELF?): Проверьте значение переменной среды LD_PRELOAD, поскольку Valgrind работает путем предварительной загрузки библиотек . Я использую следующий тест на C, чтобы проверить, содержит ли LD_PRELOAD строку "/valgrind/" или "/vgpreload":
int tests_run_within_valgrind (void)
{
char *p = getenv ("LD_PRELOAD");
if (p == NULL)
return 0;
return (strstr (p, "/valgrind/") != NULL ||
strstr (p, "/vgpreload") != NULL);
}
В других системах может быть аналогичное решение. Я предлагаю следующую команду, чтобы узнать, упоминает ли среда Valgrind:
valgrind env | grep -i valgrind
Спасибо за это, уже много лет пользуюсь * grind, но интерфейс почти не трогал. Легко сделать разумным включить этот макрос в autoconf .., который автоматически включает мою отладочную printfs () и утверждения при работе под valrgind, если присутствует valgrind / valgrind.h :) Еще раз спасибо! Очень полезно