BOOST Unit Test переполнение стека

Я сейчас пользуюсь Boost Unit Test выполнить юнит-тест для моего проекта. Каждый раз, когда я запускаю модульное тестирование, у меня возникает проблема со стеком памяти. Я отлаживаю в исходный код библиотеки BOOST и обнаруживаю, что проблема заключается в вызове следующих кодов в файле unit_test_suite.hpp:

void
traverse_test_tree( test_unit_id id, test_tree_visitor& V )
{
global_i = global_i + 1;
std::cout<<global_i<<std::endl;
if( ut_detail::test_id_2_unit_type( id ) == tut_case )
traverse_test_tree( framework::get<test_case>( id ), V );
else
traverse_test_tree( framework::get<test_suite>( id ), V );
}

Информация об ошибках, которую я получил от VC10:

Unhandled exception at 0x779815de in  TestApplication.exe: 0xC00000FD: Stack overflow.

Мне было интересно, что не так с тестовой программой. Спасибо!

РЕДАКТИРОВАТЬ Основываясь на предложениях, которые я просмотрел в своих кодах, происходят очень странные вещи: если набор тестов определен в одной программе с main (), он работает; однако, если набор тестов взят из .dll, произойдет ошибка. Я перечисляю следующие коды, чтобы проиллюстрировать мою проблему:

boost::unit_test::test_suite* main_global_test_suite;
void Hellotestdll()
{
int i= 1;
int j= 2;
BOOST_CHECK(i == j);}
boost::unit_test::test_suite* get_abc_test_suite()
{
test_suite* ts = BOOST_TEST_SUITE( "unit_geometric" );
ts->add( BOOST_TEST_CASE( &Hellotestdll ) );
return ts;
}

int main( int argc, char* argv[] )
{
try
{
/**
* Step 1. obtain options
*/
char* optionLine[1024];
int len;
len = obtain_options(optionLine, argc, argv);
/**
* Step 2. perform unit test based on user's options
*/
int test_status=0;
main_global_test_suite = get_abc_test_suite();
test_status = unit_test_main(run_global_test_suite, len, optionLine);
return test_status;

}
catch(std::exception& e)
{
std::cout << e.what() << std::endl;
return 1;
}
catch (const std::string& s)
{
std::cout << s << std::endl;
return 1;
}
catch (...)
{
return 1;
}}

Вышеуказанные коды работают очень хорошо. Но если набор тестов взят из .dll, например:

// dll_header.h
namespace abc
{

ABC_EXPORT boost::unit_test::test_suite* get_geometric_test_suite();
}
// dll_header.cpp
namespace abc
{

using namespace boost;
using namespace boost::unit_test;

void Hellotestdllabc()
{
int i= 1;
int j= 2;
BOOST_CHECK(i == j);
}

boost::unit_test::test_suite* get_abc_test_suite()
{
test_suite* ts = BOOST_TEST_SUITE( "unit_abc" );

ts->add( BOOST_TEST_CASE( &Hellotestdllabc ) );return ts;
}

}

Затем, если я вызову этот набор тестов, со следующими кодами:

 int main( int argc, char* argv[] )
{
............
/**
* Step 2. perform unit test based on user's options
*/
int test_status=0;
main_global_test_suite = abc::get_abc_test_suite();
test_status = unit_test_main(run_global_test_suite, len, optionLine);
return test_status;

}

Возникнет досадная ошибка переполнения стека.

Лето проблем

  (1) boost dll with MDd (Succeed)

Если я свяжу библиотеку тестовых модулей (с определением -DBOOST_ALL_DYN_LINK -DBOOST_TEST_NO_MAIN -DBOOST_TEST_DYN_LINK -DBOOST_ALL_NO_LIB) и запущенную исполняемую программу с той же динамической библиотекой времени выполнения (Многопоточная отладка Dll (MDd)), она будет работать.

(2) boost dll with MTd (Failed)

Если библиотека тестового модуля повышения (с определением -DBOOST_ALL_DYN_LINK -DBOOST_TEST_NO_MAIN -DBOOST_TEST_DYN_LINK -DBOOST_ALL_NO_LIB) и исполняемая исполняемая программа компилируются и связываются с одним и тем же статическим библиотечным файлом времени выполнения (Multi-thred Debu (MTd)), у меня будет сбой, но сбой отличается от того, о котором я сообщил выше:
введите описание изображения здесь

(3) boost static lib with MDd (Failed)

Если буст построен как статическая библиотека (с определением -DBOOST_TEST_NO_MAIN -DBOOST_ALL_NO_LIB), и как библиотека Boost, так и исполняемая программа построены с использованием одной динамической библиотеки времени выполнения (MDd). Произойдет следующее падение:
введите описание изображения здесь

(4) boost static lib with MTd (Failed)

Если буст построен как статическая библиотека (с определением -DBOOST_TEST_NO_MAIN -DBOOST_ALL_NO_LIB), и как библиотека Boost, так и исполняемая программа построены с использованием одной и той же статической библиотеки времени выполнения (MTd). Произойдет следующее падение:
введите описание изображения здесь

1

Решение

   ABC_EXPORT boost::unit_test::test_suite* get_geometric_test_suite();

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

Функции в DLL, которая возвращает указатели на объекты C ++, являются проблемой в целом. Это будет хорошим концом только тогда, когда компоновка объекта C ++ точно соответствует предположениям, сделанным компилятором, когда он компилировал и вашу DLL, и ваш EXE. И что объект живет в куче, к которой имеют доступ оба модуля, что требуется, поскольку DLL создает объект, а ваш EXE должен его удалить.

Чтобы объект был должным образом удален, как DLL, так и EXE должен поделиться той же версией CRT. У вас будут проблемы, когда вы создадите свою программу с / MT, запрашивая статическую версию CRT. Соответствующая настройка компилятора — C / C ++, Генерация кода, Настройка библиотеки времени выполнения. Ваша конфигурация отладки должна использовать / MDd, ваша конфигурация выпуска должна использовать / MD. Как для EXE, так и для проекта DLL, а также для библиотеки Boost, когда она была скомпилирована. Если это / MTd и / MT, то DLL будет иметь свою собственную копию CRT, связанную с ней, и будет использовать свою собственную кучу для выделения. EXE не может правильно удалить объект, так как он использует другой куча. В любом случае это приведет к неопределенному поведению. Может случиться что угодно, вам, как правило, везет только тогда, когда вы запускаете свою программу в более новой версии Windows, чем XP. Vista и выше будут использовать кучу отладки, когда вы запускаете свой тестовый модуль с подключенным отладчиком, она вызывает точку останова, когда замечает, что указатель, переданный на :: operator delete, недействителен. Обязательно разрешите компоновщику автоматически находить правильный Boost .lib для ссылки, не заставляйте его самостоятельно.

Расположение объекта является более вероятной вашей проблемой, к сожалению, гораздо сложнее диагностировать. Вы можете избежать проблем, создавая свои EXE и DLL с точно такими же настройками компилятора. С дополнительным требованием, чтобы они соответствовали параметрам, которые использовались для создания библиотек Boost. Что, безусловно, самая сложная часть, требующая машины времени. В частности, макрос _HAS_ITERATOR_DEBUGGING является источником проблем, базовые классы STL, такие как std :: vector, будут иметь разную компоновку, которая зависит от значения этого макроса.

Я понимаю, что это очень расплывчато, но в вопросе недостаточно информации, чтобы действительно диагностировать эту проблему. Самая простая проверка, которую вы можете сделать, — поместить возвращенный указатель boost :: unit_test :: test_suite в выражение наблюдения. Если вы внезапно увидите, что члены этого объекта меняются, когда вы входите в код Boost, тогда вы знать у вас проблема с макетом объекта. Дальнейшее непредсказуемо, переполнение стека, безусловно, возможно. Еще одна диагностика заключается в использовании окна Debug + Windows + Registers. Убедитесь, что значение регистра ESP стабильно при переходе по функциям.

2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]