6

I'm trying to utilize Boost.Test in Visual Studio 2010, and I'm having some trouble getting it to work. Here's the source:

#include "stdafx.hpp"

#define BOOST_TEST_MODULE (main)
#include <boost/test/unit_test.hpp>

BOOST_AUTO_TEST_CASE(morphology)
{
    BOOST_CHECK(true);
}

stdafx.hpp is literally empty. The project was created as an empty C++ project, set to build an application, with directories set up to point to boost headers and libs. I'm using /entry to point to the main function provided by Boost.Test.

There seem to be a couple of things going on. Firstly, at build time, the linker reports warnings over all the objects in the test lib, claiming ".CRT section exists; there may be unhandled static initializers or terminators":

1>msvcprtd.lib(locale0_implib.obj) : warning LNK4210: .CRT section exists; there may be unhandled static initializers or terminators
1>morphology.obj : warning LNK4210: .CRT section exists; there may be unhandled static initializers or terminators
1>libboost_unit_test_framework-vc100-mt-gd-1_49.lib(unit_test_main.obj) : warning LNK4210: .CRT section exists; there may be unhandled static initializers or terminators
1>libboost_unit_test_framework-vc100-mt-gd-1_49.lib(framework.obj) : warning LNK4210: .CRT section exists; there may be unhandled static initializers or terminators
1>libboost_unit_test_framework-vc100-mt-gd-1_49.lib(test_tools.obj) : warning LNK4210: .CRT section exists; there may be unhandled static initializers or terminators
1>libboost_unit_test_framework-vc100-mt-gd-1_49.lib(unit_test_log.obj) : warning LNK4210: .CRT section exists; there may be unhandled static initializers or terminators
1>libboost_unit_test_framework-vc100-mt-gd-1_49.lib(unit_test_suite.obj) : warning LNK4210: .CRT section exists; there may be unhandled static initializers or terminators
1>libboost_unit_test_framework-vc100-mt-gd-1_49.lib(results_reporter.obj) : warning LNK4210: .CRT section exists; there may be unhandled static initializers or terminators
1>libboost_unit_test_framework-vc100-mt-gd-1_49.lib(results_collector.obj) : warning LNK4210: .CRT section exists; there may be unhandled static initializers or terminators
1>libboost_unit_test_framework-vc100-mt-gd-1_49.lib(unit_test_parameters.obj) : warning LNK4210: .CRT section exists; there may be unhandled static initializers or terminators
1>libboost_unit_test_framework-vc100-mt-gd-1_49.lib(unit_test_monitor.obj) : warning LNK4210: .CRT section exists; there may be unhandled static initializers or terminators
1>libboost_unit_test_framework-vc100-mt-gd-1_49.lib(debug.obj) : warning LNK4210: .CRT section exists; there may be unhandled static initializers or terminators
1>libboost_unit_test_framework-vc100-mt-gd-1_49.lib(progress_monitor.obj) : warning LNK4210: .CRT section exists; there may be unhandled static initializers or terminators
1>libboost_unit_test_framework-vc100-mt-gd-1_49.lib(plain_report_formatter.obj) : warning LNK4210: .CRT section exists; there may be unhandled static initializers or terminators
1>libboost_unit_test_framework-vc100-mt-gd-1_49.lib(xml_report_formatter.obj) : warning LNK4210: .CRT section exists; there may be unhandled static initializers or terminators

Art runtime, the test application crashes somewhere in the Boost.Test library under the call tree of the main provided by Boost.Test:

>   Pentachoron.Test.exe!std::list<boost::shared_ptr<boost::runtime::cla::parameter>,std::allocator<boost::shared_ptr<boost::runtime::cla::parameter> > >::begin()  Line 787 + 0x13 bytes   C++
    Pentachoron.Test.exe!boost::unit_test::for_each::begin<std::list<boost::shared_ptr<boost::runtime::cla::parameter>,std::allocator<boost::shared_ptr<boost::runtime::cla::parameter> > > >(const std::list<boost::shared_ptr<boost::runtime::cla::parameter>,std::allocator<boost::shared_ptr<boost::runtime::cla::parameter> > > & t, boost::mpl::bool_<1> __formal)  Line 107 + 0xf bytes  C++
    Pentachoron.Test.exe!boost::runtime::cla::parser::operator[](boost::unit_test::basic_cstring<char const > string_id)  Line 169 + 0x41 bytes C++
    Pentachoron.Test.exe!boost::unit_test::runtime_config::`anonymous namespace'::retrieve_parameter<std::basic_string<char,std::char_traits<char>,std::allocator<char> > >(boost::unit_test::basic_cstring<char const > parameter_name, const boost::runtime::cla::parser & s_cla_parser, const std::basic_string<char,std::char_traits<char>,std::allocator<char> > & default_value, const std::basic_string<char,std::char_traits<char>,std::allocator<char> > & optional_value)  Line 216 + 0x34 bytes  C++
    Pentachoron.Test.exe!boost::unit_test::runtime_config::report_sink()  Line 470 + 0x8b bytes C++
    Pentachoron.Test.exe!boost::unit_test::results_reporter::`anonymous namespace'::results_reporter_impl::results_reporter_impl()  Line 59 + 0x31 bytes    C++
    Pentachoron.Test.exe!boost::unit_test::results_reporter::`anonymous namespace'::s_rr_impl()  Line 91 + 0x35 bytes   C++
    Pentachoron.Test.exe!boost::unit_test::results_reporter::get_stream()  Line 120 + 0x5 bytes C++
    Pentachoron.Test.exe!`boost::unit_test::unit_test_main'::`1'::catch$3()  Line 207 + 0x5 bytes   C++
    msvcr100d.dll!_CallSettingFrame()  Line 44  Asm
    msvcr100d.dll!__CxxCallCatchBlock(_EXCEPTION_RECORD * pExcept)  Line 1337 + 0x15 bytes  C++
    ntdll.dll!0000000077c50c21()    
    [Frames below may be incorrect and/or missing, no symbols loaded for ntdll.dll] 
    Pentachoron.Test.exe!boost::unit_test::unit_test_main(boost::unit_test::test_suite * (int, char * *)* init_func, int argc, char * * argv)  Line 179 C++
    Pentachoron.Test.exe!main(int argc, char * * argv)  Line 238    C++
    kernel32.dll!000000007753652d()     
    ntdll.dll!0000000077c2c521()    

Please....someone tell me there's just a compiler flag I didn't set, or something stupid like that...

Ben Collins
  • 20,538
  • 18
  • 127
  • 187
  • [This may be helpful in resolving your issue](http://stackoverflow.com/questions/6529003/crt-section-what-does-this-warning-mean). On a cursory pass in Google, this is the best I can find at the moment. – MrGomez Mar 28 '12 at 21:02
  • Yeah, that was the first thing I found, too. The MSDN suggestions don't seem helpful, because by default even an empty project links against the C and C++ runtime libs. Also, I'm already "not using /noentry" by the virtue of using `/entry`. – Ben Collins Mar 28 '12 at 21:05
  • To be sure -- you built Boost yourself? If so, what options did you pass to bjam/b2? – ildjarn Mar 28 '12 at 22:13
  • @ildjarn: I didn't. I'm using the 64-bit libs built here: http://boost.teeks99.com/. – Ben Collins Mar 29 '12 at 15:47
  • Another thing that had occurred to me is that I'm using the Platform SDK 7.1 toolset, but the boost libs from teeks99 all have the vc100 suffix on them, and afaik, the only way to build boost with the platform toolset would be to customize the jamfiles (ugh). Right? – Ben Collins Mar 29 '12 at 16:20
  • That's definitely something to investigate. I've never manually changed the toolset other than using `--toolset=msvc address-model=64` when building for x64 myself. – Soo Wei Tan Mar 29 '12 at 17:28
  • Agreed with @Soo -- I think the first step is to build Boost yourself. Instructions are [here](http://www.boost.org/more/getting_started/windows.html). – ildjarn Mar 29 '12 at 18:30
  • Yeah. I'm working through the builds now - although I'm not entirely sure if I'm building with the platform toolkit or not, or if that even matters. – Ben Collins Mar 29 '12 at 20:09
  • Whether you use the platform SDK that comes with VC++ or a separate one is dictated entirely by the environment variables set when you invoke bjam. I.e., if you run "Visual Studio Command Prompt" you'll get the former, and if you run "Windows SDK 7.1 Command Prompt" you'll get the latter. I doubt it makes any difference, though, since nothing inside of Boost.Build sets `WINVER`. – ildjarn Mar 29 '12 at 21:24

2 Answers2

10

Alright, I got it figured out. The problem was caused by me setting /entry to point directly to main, which bypasses all the static object constructors and runtime intialization. Once I set the /subsystem:console option and just let the compiler set up the runtime correctly and call the main function supplied by Boost.Test, it worked as expected.

What a hassle.

The /subsystem:console parameter is for the MSVC linker. To configure this, right-click your project, go to Linker|Command Line , and add /subsystem:console to Additional Options at the bottom of the dialog. (VS2013)

Steve
  • 6,334
  • 4
  • 39
  • 67
Ben Collins
  • 20,538
  • 18
  • 127
  • 187
1

I use Boost.Test on x64 with no problems.

Can you verify that the C runtime libraries you are linking in your application matches the one used by Boost? Boost appears to be using /MDd according to your linker output. (See MSDN).

Soo Wei Tan
  • 3,262
  • 2
  • 34
  • 36
  • Output of `dumpbin /all .\libboost_unit_test_framework-vc100-mt-gd-1_49.lib | select-string DEFAULTLIB` shows `msvcprtd` and `MSVCRTD`. I'm using `/MDd` in my application (which links to `MSVCRTD`). – Ben Collins Mar 28 '12 at 21:46
  • So how do you set up your project? – Ben Collins Mar 28 '12 at 21:49
  • According to the [Boost naming scheme](http://www.boost.org/doc/libs/1_49_0/more/getting_started/windows.html#library-naming), `-mt-gd` means multithreaded debug (non-statically linked). Does this match the default settings (/MDd in project settings)? – Soo Wei Tan Mar 28 '12 at 21:53
  • I added `#include ` in my stdafx.h, using `/MD` in release and `/MDd` in debug. My entry point is not set, and I'm not using /NOENTRY. Does cross compiling for Win32 work? – Soo Wei Tan Mar 28 '12 at 21:56
  • I'm not sure what the default is, but I"m using /MDd (in Debug) – Ben Collins Mar 29 '12 at 15:58