3

Following an example on net From this answer I came up with this:

int server_port;
auto value_port = new po::typed_value<int>(&server_port); //<-- Really??
value_port->value_name("port");

po::options_description opt_config("Configuation");
opt_config.add_options()("port,P", value_port, "listening port");

This apparently works. However explicitly calling new to create raw pointers in C++ raised alarm bells.


So the first thing I tried was to use a statically allocated object. (I don’t see the need for dynamically allocated memory here):

auto value_port = po::typed_value<int>(&server_port);
value_port.value_name("port");

po::options_description opt_config("Configuation");
opt_config.add_options()("port,P", &value_port, "listening port");

This gives a run time error at function exit (when variables are being destructed).
The call stack starts with

  • boost::detail::shared_count::~shared_count() Line 447

and the error is at

  • boost::checked_delete<boost::program_options::value_semantic const >(const boost::program_options::value_semantic * x) Line 34

where there is a delete instruction.


The second thing I tried was to use unique_ptr (from std):

auto value_port = make_unique<po::typed_value<int>>(&server_port);
value_port->value_name("port");

po::options_description opt_config("Configuation");
opt_config.add_options()("port,P", value_port.get(), "listening port");

The story is similar, with 2 frames this time on the call stack:

  • std::unique_ptr<boost::program_options::typed_value<int,char>,std::default_delete<boost::program_options::typed_value<int,char> > >::~unique_ptr<boost::program_options::typed_value<int,char>,std::default_delete<boost::program_options::typed_value<int,char> > >() Line 1449

  • std::default_delete<boost::program_options::typed_value<int,char> >::operator()(boost::program_options::typed_value<int,char> * _Ptr) Line 1200

again at a delete instruction.


So it seems like options_description destructs (the object at) the pointer received via add_options and the problem is caused by 2 destructions on the same object.

Shouldn’t this be documented? Doesn’ț this goes against RAII? The caller creates the object, but it is destroyed by another object that at some point receives a pointer to it. `


I used boost_1_56_0 with Visual Sudio 2013 running a debug x64 configuration.

Community
  • 1
  • 1
bolov
  • 72,283
  • 15
  • 145
  • 224
  • It's kinda [mentioned](http://www.boost.org/doc/libs/1_56_0/doc/html/boost/program_options/option_description.html#boost.program_options.option_descriptionconstruct-copy-destruct) in docs but current design is really ugly. The recommended way is to use po::value that creates po::typed_value via "new" anyway though. – dewaffled Oct 19 '14 at 10:27
  • 1
    @frymode it mentions the motivation behind using raw pointers, it does not mention that it takes ownership of the pointer. The only mention of ownership is: `Note: it would be nice to make the second parameter auto_ptr, to explicitly pass ownership.` This statement doesn’t make it clear that it actually takes ownership. – bolov Oct 19 '14 at 10:48
  • One of the problem with the boost libraries, is that by maintaining compatibility with C++03, their design can be suboptimal for further versions. In C++11, a `unique_ptr` would be the go-to idiom to express this passing of ownership; in C++03 some people used raw pointers because `auto_ptr` was despised (due to its awkward copy semantics). – Matthieu M. Oct 19 '14 at 13:45

1 Answers1

0

The way you use it is indeed not exactly RAII. unique_ptr is a nice try. What you have to do is to call release() instead of get():

opt_config.add_options()("port,P", value_port.release(), "listening port");
facetus
  • 1,091
  • 6
  • 20