Skip to content

Commit a43b174

Browse files
cfrandsencfrandsen
cfrandsen
authored and
cfrandsen
committed
Update value_semantic to return a boost shared pointer instead of a raw pointer
This will return a managed pointer to the user instead of an unmanaged pointer. This helps static code analyzers from flagged false positive memory leaks It is becoming harder and harder for projects to use this project because some customers require a static code analyzer. By returning a managed pointer, those projects can continue to use this amazing library.
1 parent 7bcbb4e commit a43b174

10 files changed

+139
-91
lines changed

Diff for: include/boost/program_options/detail/value_semantic.hpp

+7-6
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
// This file defines template functions that are declared in
77
// ../value_semantic.hpp.
88

9+
#include <boost/smart_ptr/make_shared.hpp>
910
#include <boost/throw_exception.hpp>
1011

1112
// forward declaration
@@ -185,34 +186,34 @@ namespace boost { namespace program_options {
185186
}
186187

187188
template<class T>
188-
typed_value<T>*
189+
shared_ptr<typed_value<T>>
189190
value()
190191
{
191192
// Explicit qualification is vc6 workaround.
192193
return boost::program_options::value<T>(0);
193194
}
194195

195196
template<class T>
196-
typed_value<T>*
197+
shared_ptr<typed_value<T>>
197198
value(T* v)
198199
{
199-
typed_value<T>* r = new typed_value<T>(v);
200+
shared_ptr<typed_value<T>> r = boost::make_shared<typed_value<T>>(v);
200201

201202
return r;
202203
}
203204

204205
template<class T>
205-
typed_value<T, wchar_t>*
206+
shared_ptr<typed_value<T, wchar_t>>
206207
wvalue()
207208
{
208209
return wvalue<T>(0);
209210
}
210211

211212
template<class T>
212-
typed_value<T, wchar_t>*
213+
shared_ptr<typed_value<T, wchar_t>>
213214
wvalue(T* v)
214215
{
215-
typed_value<T, wchar_t>* r = new typed_value<T, wchar_t>(v);
216+
shared_ptr<typed_value<T, wchar_t>> r = boost::make_shared<typed_value<T, wchar_t>>(v);
216217

217218
return r;
218219
}

Diff for: include/boost/program_options/options_description.hpp

+11-2
Original file line numberDiff line numberDiff line change
@@ -75,12 +75,12 @@ namespace program_options {
7575
after \-- short name.
7676
*/
7777
option_description(const char* name,
78-
const value_semantic* s);
78+
shared_ptr<const value_semantic> s);
7979

8080
/** Initializes the class with the passed data.
8181
*/
8282
option_description(const char* name,
83-
const value_semantic* s,
83+
shared_ptr<const value_semantic> s,
8484
const char* description);
8585

8686
virtual ~option_description();
@@ -167,6 +167,15 @@ namespace program_options {
167167
operator()(const char* name,
168168
const char* description);
169169

170+
options_description_easy_init&
171+
operator()(const char* name,
172+
shared_ptr<const value_semantic> s);
173+
174+
options_description_easy_init&
175+
operator()(const char* name,
176+
shared_ptr<const value_semantic> s,
177+
const char* description);
178+
170179
options_description_easy_init&
171180
operator()(const char* name,
172181
const value_semantic* s);

Diff for: include/boost/program_options/value_semantic.hpp

+29-27
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <boost/any.hpp>
1313
#include <boost/function/function1.hpp>
1414
#include <boost/lexical_cast.hpp>
15+
#include <boost/smart_ptr/enable_shared_from_this.hpp>
1516

1617
#include <string>
1718
#include <vector>
@@ -178,7 +179,8 @@ namespace boost { namespace program_options {
178179

179180
/** Class which handles value of a specific type. */
180181
template<class T, class charT = char>
181-
class typed_value : public value_semantic_codecvt_helper<charT>
182+
class typed_value : public enable_shared_from_this<typed_value<T, charT>>,
183+
public value_semantic_codecvt_helper<charT>
182184
#ifndef BOOST_NO_RTTI
183185
, public typed_value_base
184186
#endif
@@ -196,11 +198,11 @@ namespace boost { namespace program_options {
196198
if none is explicitly specified. The type 'T' should
197199
provide operator<< for ostream.
198200
*/
199-
typed_value* default_value(const T& v)
201+
shared_ptr<typed_value> default_value(const T& v)
200202
{
201203
m_default_value = boost::any(v);
202204
m_default_value_as_text = boost::lexical_cast<std::string>(v);
203-
return this;
205+
return shared_from_this();
204206
}
205207

206208
/** Specifies default value, which will be used
@@ -209,30 +211,30 @@ namespace boost { namespace program_options {
209211
but textual representation of default value must be provided
210212
by the user.
211213
*/
212-
typed_value* default_value(const T& v, const std::string& textual)
214+
shared_ptr<typed_value> default_value(const T& v, const std::string& textual)
213215
{
214216
m_default_value = boost::any(v);
215217
m_default_value_as_text = textual;
216-
return this;
218+
return shared_from_this();
217219
}
218220

219221
/** Specifies an implicit value, which will be used
220222
if the option is given, but without an adjacent value.
221223
Using this implies that an explicit value is optional,
222224
*/
223-
typed_value* implicit_value(const T &v)
225+
shared_ptr<typed_value> implicit_value(const T &v)
224226
{
225227
m_implicit_value = boost::any(v);
226228
m_implicit_value_as_text =
227229
boost::lexical_cast<std::string>(v);
228-
return this;
230+
return shared_from_this();
229231
}
230232

231233
/** Specifies the name used to to the value in help message. */
232-
typed_value* value_name(const std::string& name)
234+
shared_ptr<typed_value> value_name(const std::string& name)
233235
{
234236
m_value_name = name;
235-
return this;
237+
return shared_from_this();
236238
}
237239

238240
/** Specifies an implicit value, which will be used
@@ -245,36 +247,36 @@ namespace boost { namespace program_options {
245247
operator<< for ostream, but textual representation of default
246248
value must be provided by the user.
247249
*/
248-
typed_value* implicit_value(const T &v, const std::string& textual)
250+
shared_ptr<typed_value> implicit_value(const T &v, const std::string& textual)
249251
{
250252
m_implicit_value = boost::any(v);
251253
m_implicit_value_as_text = textual;
252-
return this;
254+
return shared_from_this();
253255
}
254256

255257
/** Specifies a function to be called when the final value
256258
is determined. */
257-
typed_value* notifier(function1<void, const T&> f)
259+
shared_ptr<typed_value> notifier(function1<void, const T&> f)
258260
{
259261
m_notifier = f;
260-
return this;
262+
return shared_from_this();
261263
}
262264

263265
/** Specifies that the value is composing. See the 'is_composing'
264266
method for explanation.
265267
*/
266-
typed_value* composing()
268+
shared_ptr<typed_value> composing()
267269
{
268270
m_composing = true;
269-
return this;
271+
return shared_from_this();
270272
}
271273

272274
/** Specifies that the value can span multiple tokens.
273275
*/
274-
typed_value* multitoken()
276+
shared_ptr<typed_value> multitoken()
275277
{
276278
m_multitoken = true;
277-
return this;
279+
return shared_from_this();
278280
}
279281

280282
/** Specifies that no tokens may be provided as the value of
@@ -284,17 +286,17 @@ namespace boost { namespace program_options {
284286
'implicit_value' method should be also used. In most
285287
cases, you can use the 'bool_switch' function instead of
286288
using this method. */
287-
typed_value* zero_tokens()
289+
shared_ptr<typed_value> zero_tokens()
288290
{
289291
m_zero_tokens = true;
290-
return this;
292+
return shared_from_this();
291293
}
292294

293295
/** Specifies that the value must occur. */
294-
typed_value* required()
296+
shared_ptr<typed_value> required()
295297
{
296298
m_required = true;
297-
return this;
299+
return shared_from_this();
298300
}
299301

300302
public: // value semantic overrides
@@ -381,39 +383,39 @@ namespace boost { namespace program_options {
381383
value of option into program variable.
382384
*/
383385
template<class T>
384-
typed_value<T>*
386+
shared_ptr<typed_value<T>>
385387
value();
386388

387389
/** @overload
388390
*/
389391
template<class T>
390-
typed_value<T>*
392+
shared_ptr<typed_value<T>>
391393
value(T* v);
392394

393395
/** Creates a typed_value<T> instance. This function is the primary
394396
method to create value_semantic instance for a specific type, which
395397
can later be passed to 'option_description' constructor.
396398
*/
397399
template<class T>
398-
typed_value<T, wchar_t>*
400+
shared_ptr<typed_value<T, wchar_t>>
399401
wvalue();
400402

401403
/** @overload
402404
*/
403405
template<class T>
404-
typed_value<T, wchar_t>*
406+
shared_ptr<typed_value<T, wchar_t>>
405407
wvalue(T* v);
406408

407409
/** Works the same way as the 'value<bool>' function, but the created
408410
value_semantic won't accept any explicit value. So, if the option
409411
is present on the command line, the value will be 'true'.
410412
*/
411-
BOOST_PROGRAM_OPTIONS_DECL typed_value<bool>*
413+
BOOST_PROGRAM_OPTIONS_DECL shared_ptr<typed_value<bool>>
412414
bool_switch();
413415

414416
/** @overload
415417
*/
416-
BOOST_PROGRAM_OPTIONS_DECL typed_value<bool>*
418+
BOOST_PROGRAM_OPTIONS_DECL shared_ptr<typed_value<bool>>
417419
bool_switch(bool* v);
418420

419421
}}

Diff for: src/options_description.cpp

+23-5
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
// FIXME: this is only to get multiple_occurrences class
1212
// should move that to a separate headers.
1313
#include <boost/program_options/parsers.hpp>
14+
#include <boost/smart_ptr/make_shared.hpp>
1415

1516

1617
#include <boost/lexical_cast.hpp>
@@ -50,7 +51,7 @@ namespace boost { namespace program_options {
5051

5152
option_description::
5253
option_description(const char* names,
53-
const value_semantic* s)
54+
shared_ptr<const value_semantic> s)
5455
: m_value_semantic(s)
5556
{
5657
this->set_names(names);
@@ -59,7 +60,7 @@ namespace boost { namespace program_options {
5960

6061
option_description::
6162
option_description(const char* names,
62-
const value_semantic* s,
63+
shared_ptr<const value_semantic> s,
6364
const char* description)
6465
: m_description(description), m_value_semantic(s)
6566
{
@@ -266,7 +267,7 @@ namespace boost { namespace program_options {
266267
// no value can be specified on command line.
267268
// FIXME: does not look exception-safe
268269
shared_ptr<option_description> d(
269-
new option_description(name, new untyped_value(true), description));
270+
new option_description(name, boost::make_shared<untyped_value>(true), description));
270271

271272
owner->add(d);
272273
return *this;
@@ -275,7 +276,7 @@ namespace boost { namespace program_options {
275276
options_description_easy_init&
276277
options_description_easy_init::
277278
operator()(const char* name,
278-
const value_semantic* s)
279+
shared_ptr<const value_semantic> s)
279280
{
280281
shared_ptr<option_description> d(new option_description(name, s));
281282
owner->add(d);
@@ -285,14 +286,31 @@ namespace boost { namespace program_options {
285286
options_description_easy_init&
286287
options_description_easy_init::
287288
operator()(const char* name,
288-
const value_semantic* s,
289+
shared_ptr<const value_semantic> s,
289290
const char* description)
290291
{
291292
shared_ptr<option_description> d(new option_description(name, s, description));
292293

293294
owner->add(d);
294295
return *this;
295296
}
297+
298+
options_description_easy_init&
299+
options_description_easy_init::
300+
operator()(const char* name,
301+
const value_semantic* s)
302+
{
303+
return (*this)(name, shared_ptr<const value_semantic>(s));
304+
}
305+
306+
options_description_easy_init&
307+
options_description_easy_init::
308+
operator()(const char* name,
309+
const value_semantic* s,
310+
const char* description)
311+
{
312+
return (*this)(name, shared_ptr<const value_semantic>(s), description);
313+
}
296314

297315
const unsigned options_description::m_default_line_length = 80;
298316

Diff for: src/value_semantic.cpp

+4-3
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <boost/program_options/value_semantic.hpp>
99
#include <boost/program_options/detail/convert.hpp>
1010
#include <boost/program_options/detail/cmdline.hpp>
11+
#include <boost/smart_ptr/make_shared.hpp>
1112
#include <set>
1213

1314
#include <cctype>
@@ -121,16 +122,16 @@ namespace boost { namespace program_options {
121122
value_store = new_tokens.empty() ? std::string("") : new_tokens.front();
122123
}
123124

124-
BOOST_PROGRAM_OPTIONS_DECL typed_value<bool>*
125+
BOOST_PROGRAM_OPTIONS_DECL shared_ptr<typed_value<bool>>
125126
bool_switch()
126127
{
127128
return bool_switch(0);
128129
}
129130

130-
BOOST_PROGRAM_OPTIONS_DECL typed_value<bool>*
131+
BOOST_PROGRAM_OPTIONS_DECL shared_ptr<typed_value<bool>>
131132
bool_switch(bool* v)
132133
{
133-
typed_value<bool>* r = new typed_value<bool>(v);
134+
shared_ptr<typed_value<bool>> r = boost::make_shared<typed_value<bool>>(v);
134135
r->default_value(0);
135136
r->zero_tokens();
136137

Diff for: test/cmdline_test.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ void apply_syntax(options_description& desc,
7171
stringstream ss;
7272
ss << syntax;
7373
while(ss >> s) {
74-
value_semantic* v = 0;
74+
boost::shared_ptr<value_semantic> v = 0;
7575

7676
if (*(s.end()-1) == '=') {
7777
v = value<string>();

0 commit comments

Comments
 (0)