Passing Pointers -- where to delete them

J

James Kanze

Unit tests - you would want the object reset before each test.
[/QUOTE]
Maybe. But you need to be very careful when using singletons
in an application that you are eventually going to be doing
unit testing on; especially if your singleton becomes too
monstrous and starts to contain information used in many
unrelated situations.

That's a design error. Just don't do it. There's no law that
says that an application cannot have more than one, unrelated
singleton.
For one, your unit test code couldn't be completely
self-contained, in that you have to modify the singleton's
code to generate "fake" states. So if you were performing many
different test cases, the singleton would have to be aware of
the cases. Also, making sure that your simulated application
states *do* in fact represent the state you want to test is a
task that may require testing in itself, because you end up
having to fudge all of the singleton's data to make it
completely valid when in fact you are testing a part of your
code that uses only a very small subset of it.
I usually avoid singletons when I know I'm going to have to do
detailed unit testing

Is there *ever* a case when you don't have to do detailed unit
testing. It's a necessary (but not sufficient) condition for
reliable software.
-- not because it's necessarily a bad, evil thing but because
I find it much easier to keep everything separate than lumping
it into a singleton class (which, even if I try not to "lump
everything together", the tendency is there -- perhaps it's
just a personal flaw). If you can design the software with
unit testing in mind from the start, you can keep the
components a bit more isolated, and therefore easier to test.
I find when I use a singleton it starts to blur the lines
between different parts in my application, just by it's
nature.

That's a curious observation. Most of my singletons are in
components. They can't lump things together, because they don't
know about anything else. At the application level, I'll more
often use a local variable in main, rather than a singleton.
In any case, I shouldn't have said "well, if it's a singleton,
why would you want to reset it?";

I'm not sure. It depends on what you meant be "reset it". If
you meant "delete the object and create a new one", then it's
not a singleton if you do.
because it's more a matter of personal taste, I guess, and I
try not to show bias about these kinds of things. But now that
the cat's out of the bag: I do not like singletons very much.
I have never found myself in a situation where there wasn't a
better way.

Like most things, they can be overused, but a few special cases
do occur to me. I use at least two regularly: one for "program
state" (which will define the return value of main in the end),
and one for the command line---the "options" are static
variables which enrol with it, and are automatically processed
when the singleton object is passed argc and argv. My
configuration file data is usually a singleton as well, as is
the log manager.
 
K

keith

FYI, the "smart pointer" concept being referred to here is a concept
that typically involves using a template class of some sort to wrap
object creation and destruction, so that the object is automatically
destroyed when it goes out of scope. For example, something like (I
made up MySmartPtr):

void function () {
MySmartPtr<Object> ptr; // automagically new's an Object
Object *x = ptr; // i can use it like a pointer
ptr->MemberFunction(); // same here
} // Object automagically deleted when ptr goes out of scope.

Some smart pointer types even have built in reference counting, which
can be very convenient in many situations.

Can I ask you to clarify this please? In boost/scoped_ptr.hpp there
is no mention of 'new', and I always have a constructor similar to
this:

{.....
private:
boost::scoped_ptr<whatever> p_;
......
MyObject() : p_(new whatever()) {}
.....
};

I don't see anything 'automagically' getting new'ed. Am I
misunderstanding what you were saying here?
 
K

Krice

is it okay to assume that the function can delete that pointer,
or should I delete the pointer in my function only.

You should delete the object when it's safe to do it.
And also I read somewhere it is always good to pass objects
by reference

Maybe, but you don't have to do that.
 
R

Richard Herring

In message
Can I ask you to clarify this please? In boost/scoped_ptr.hpp there
is no mention of 'new', and I always have a constructor similar to
this:

{.....
private:
boost::scoped_ptr<whatever> p_;
.....
MyObject() : p_(new whatever()) {}
....
};

I don't see anything 'automagically' getting new'ed. Am I
misunderstanding what you were saying here?
He's not talking about the boost pointers, but some hypothetical
MySmartPtr, whose constructor even more automagically knows which of
Object's derived classes to construct and what arguments its constructor
needs.

For obvious reasons it's not usual to wrap _creation_ of the object
inside real smart pointers. There are usually also good reasons for not
allowing implicit conversion to the raw pointer type.
 
J

jason.cipriani

On Mar 3, 1:34 am, "(e-mail address removed)"

I can think of one or two cases myself, but the original context
was responding to relative beginner, and your recommendations
for how to manage memory all seemed to concern situations where
you would normally not use dynamic memory to begin with.

The reason that I pointed them out is that I think it's important to
give examples like that to beginners, especially when the topic starts
getting into "NEVER DO THIS IT'S EVIL" territory (such as this topic,
or "goto", things like that). The goal is to keep the O.P. open-
minded. It bothers me to no end when I see somebody say "I was told
not to program this way because it was bad". I am just adding more
info to prevent that.
The obvious answer to that is to change compilers:).

If only life were that simple. :-(
But the case of a factory is precisely the case where you do NOT
delete where you new'ed. The case where your recommendation
doesn't hold.

I do not understand what you mean. When using a factory I frequently
allow the created objects to be deleted. It's not always the case that
you'd want the lifetime of an object created that way would always be
until the program ends. I wouldn't be against a creative way of
implementing a factory (e.g.) that didn't use 'new' to dynamically
create objects, but I don't know how to do that.
3) When dynamic allocation is the only solution; such as an
application where user actions directly lead to the creation
and destruction of objects, and so you don't know what you
need to have created at compile time.

[snip] And
again, it's precisely a case where construction and destruction
don't come in a literal pair; [snip]

Well I suppose it depends on how you look at it: I see "user wants to
add something" and "user wants to remove something" as a literal pair.
[snip] My point was that
the ways you presented for managing dynamic memory were not
relevant, because they could only be applied in cases where you
normally shouldn't be using dynamic memory.

My original examples were really poor, and I apologize for not saying
"by the way, this is not a good situation to use new in". Hopefully I
cleared it up in the following post. My intentions weren't to confuse.
Sorry for that.

Jason
 
J

jason.cipriani

Is there *ever* a case when you don't have to do detailed unit
testing. It's a necessary (but not sufficient) condition for
reliable software.

The one case when I do not have to do detailed unit testing is when,
for whatever reason, stability is not important given the time it
would take to test the software. The situation is uncommon but it
happens from time to time. For the most part, though, you can
translate that into "I usually avoid singletons, period".
I'm not sure. It depends on what you meant be "reset it". If
you meant "delete the object and create a new one", then it's
not a singleton if you do.

That is what I meant; that is what the original question was about,
deleting and recreating the "single" instance -- not so much resetting
it's state.
Like most things, they can be overused, but a few special cases
do occur to me. I use at least two regularly: one for "program
state" (which will define the return value of main in the end),
and one for the command line---the "options" are static
variables which enrol with it, and are automatically processed
when the singleton object is passed argc and argv. My
configuration file data is usually a singleton as well, as is
the log manager.

I sometimes use it for command line options if I need to put something
together quickly (even then I try to keep the command line data local
to main and pass around the relevant parts as needed), although I've
found a lot of merit in merging command line options and configuration
file data into the same set of configuration data. For configuration
data, I generally keep everything as static members of a class --
which does have the same end effect sans the GetInstance(), so I
suppose it's not much different; same with logging.

Jason
 
I

Ian Collins

James said:
In such cases, I'll use a separate process for each test. It's
a lot closer to the actual use case. But even then, unit tests
for singletons are somewhat difficult. Typically, the singleton
will look like a memory leak, which, of course, causes the test
to fail---you need to take special precautions to avoid this.
I guess that depends whether you allow your singletons to have public
constructors and destructors.
 
J

Jeff Schwab

Ian said:
No, I was referring to the case where a test either test or uses a
singleton.

I understand; sorry if I was too curt. What I mean is that adding a
"reset" feature to a singleton for testing purposes is a muddling of
ideas. If you need your singleton to be fresh for each test, then what
you need are setup and tear-down steps that collectively form a fixture.
If "reset" is part of the functionality supported by your singleton,
then that feature needs to be tested independently, and probably should
not serve double-duty as part of your test harness. If you have
multiple tests, each of which requires a fresh instance of your
singleton, the most straightforward solution (already suggested by James
Kanze) may be to run a separate process for each test.

There may well be solid use cases for "resettable" singletons. The dead
reference problem addressed by Loki's PhoenixSingleton comes to mind.

http://loki-lib.sourceforge.net/html/a00630.html

http://books.google.com/books?id=aJ...H-uTl4_&sig=4JF3dh23ubPnoHITZV-PU23V1UI&hl=en
 
I

Ian Collins

Jeff said:
I understand; sorry if I was too curt. What I mean is that adding a
"reset" feature to a singleton for testing purposes is a muddling of
ideas. If you need your singleton to be fresh for each test, then what
you need are setup and tear-down steps that collectively form a fixture.
If "reset" is part of the functionality supported by your singleton,
then that feature needs to be tested independently, and probably should
not serve double-duty as part of your test harness. If you have
multiple tests, each of which requires a fresh instance of your
singleton, the most straightforward solution (already suggested by James
Kanze) may be to run a separate process for each test.
Or to allow the singleton to be deleted and recreated. The singleton
may not be the target of the test, it might be a component that isn't a
suitable candidate for a mock object. One project I work with uses
singletons for each database item, created in tests by a test database
fixture.
 
J

James Kanze

On Mar 3, 5:48 am, James Kanze <[email protected]> wrote:

[...]
[concerning singletons...]
I sometimes use it for command line options if I need to put
something together quickly (even then I try to keep the
command line data local to main and pass around the relevant
parts as needed),

Actually, I've found it preferable for individual components to
handle their own options, with no global specification of the
complete list of options anywhere. At least in a lot of cases.
although I've found a lot of merit in merging command line
options and configuration file data into the same set of
configuration data.

For programs which have configuration files, it's often
desirable to allow specific configuration data to be overridden
by command line options, I agree, and my configuration
management software supports this. That doesn't mean that there
won't be options which can't appear in the configuration file.
(The name of the configuration file, for example, is almost
always a command line option.)
For configuration data, I generally keep everything as static
members of a class -- which does have the same end effect sans
the GetInstance(), so I suppose it's not much different; same
with logging.

Yes. I was using "singleton" in a more generic sense: in my
case, for example, each option is actually a static variable (at
namespace scope); CommandLine is a true singleton, however,
since it is accessed by the constructors of the options.
 
J

James Kanze

I guess that depends whether you allow your singletons to have
public constructors and destructors.

By definition, a singleton doesn't have public constructors or
destructors, at least as I understand the pattern. (At least as
I use and understand the word, singleton refers to a specific
pattern, and not to just any class which happens to be present
only once.) But that's not really the issue. My test harness
ensures that any memory allocated within the test has been freed
at the end of the test. If the first call to the instance()
function of the singleton is within the test, any memory
allocated by the creation of the singleton will appear as a leak
at the end of the test.

If the creation of the singleton is incidental to the
test---i.e. the test needs the singleton to run, but is not
testing the actual creation---then I'll just arrange to create
it before starting the tests. My test harness has special
options for this sort of thing. If the goal is to test the
instantiation process itself, on the other hand, I'll run each
test in a separate process (without memory leak checking, at
least during the creation of the singleton).
 
I

Ian Collins

James said:
By definition, a singleton doesn't have public constructors or
destructors, at least as I understand the pattern. (At least as
I use and understand the word, singleton refers to a specific
pattern, and not to just any class which happens to be present
only once.) But that's not really the issue. My test harness
ensures that any memory allocated within the test has been freed
at the end of the test. If the first call to the instance()
function of the singleton is within the test, any memory
allocated by the creation of the singleton will appear as a leak
at the end of the test.
I guess we bent the rules for our singleton objects to enable then to be
created and destroyed in tests. The single instance is enforced through
a base class template with a static member pointer. This is compared to
NULL (in an assert) and set in the object's constructor and deleted in
the destructor.

I use cppUnit, creating and deleting singletons in the setUp() and
trearDown() methods.
 
J

James Kanze

I guess we bent the rules for our singleton objects to enable
then to be created and destroyed in tests. The single
instance is enforced through a base class template with a
static member pointer.

The problem with this is that you're no longer testing the code
you actually use.
This is compared to NULL (in an assert) and set in the
object's constructor and deleted in the destructor.
I use cppUnit, creating and deleting singletons in the setUp()
and trearDown() methods.

Doesn't cppUnit support tests using separate processes? If not,
that sounds seriously limiting.
 
J

Jeff Schwab

James said:
On Mar 3, 5:48 am, James Kanze <[email protected]> wrote:

[...]
[concerning singletons...]
....
I sometimes use it for command line options if I need to put
something together quickly (even then I try to keep the
command line data local to main and pass around the relevant
parts as needed),
Actually, I've found it preferable for individual components to
handle their own options, with no global specification of the
complete list of options anywhere. At least in a lot of cases.

How do you recognize bad options? Do the components register their
flags in a table somewhere? I also don't keep the arguments around
(except in argv)), but still find I have to define them all in one
place, e.g. in a getopt format string.
 
I

Ian Collins

James said:
The problem with this is that you're no longer testing the code
you actually use.
No, the code is the code we actually use. Don't forget that everything
I or my team writes is written test fist, so the only thing is actual
production code.
Doesn't cppUnit support tests using separate processes? If not,
that sounds seriously limiting.
It might, but I've never had cause to look...
 
J

James Kanze

James said:
On Mar 3, 5:48 am, James Kanze <[email protected]> wrote:
[...]
[concerning singletons...]
Like most things, they can be overused, but a few special cases
do occur to me. ...
I sometimes use it for command line options if I need to put
something together quickly (even then I try to keep the
command line data local to main and pass around the relevant
parts as needed),
Actually, I've found it preferable for individual components to
handle their own options, with no global specification of the
complete list of options anywhere. At least in a lot of cases.
How do you recognize bad options? Do the components register
their flags in a table somewhere? I also don't keep the
arguments around (except in argv)), but still find I have to
define them all in one place, e.g. in a getopt format string.

It depends on what makes them bad. If it's an unknown option,
of course, CommandLine doesn't find it registered when it
processes argc, argv, and complains (a fatal error). If it's a
problem with an argument to the option (supposing there is one),
that's up to the actual option to handle.

Of course, I still do have to define them all in one place: the
man page:). (With getopt, of course, I'd have to define them
there as well.)

If you're interested, the code is on line. Not the very latest
version, but these particular components haven't changed that
much. (Or have they? I know I added support for positional
dependent options at one point, things like the -l option of the
compiler. It may not be in the version currently on line.)
 
J

James Kanze

[...]
No, the code is the code we actually use.

But the context it's tested in isn't. Especially if you're
"resetting" a singleton. (I suppose that if you're actually
destructing the object, and renew'ing it, the difference is
minor. But I can still imagine cases where it might make a
difference.)
Don't forget that everything I or my team writes is written
test first, so the only thing is actual production code.

Except, of course, that it's running in a different environment.
That's partially unavoidable, of course, but in code that I
expect to be run before main(), I do ensure that it's tested
running before main(). (One problem I've seen in the past is
using std::cout or std::cerr before they've been constructed.
Regretfully, even ensuring that you're testing the code before
main doesn't ensure that you're verifying that it takes the
necessary steps to avoid this---it's quite possible that just by
chance, the objects were constructed first anyway.)
It might, but I've never had cause to look...

I suspect it does. It's got a pretty good reputation. But
designing a test harness to test things like correctly defending
against order of initialization problems is very difficult. For
the same reason that you have the problems to begin with: you
can't ensure externally that A is constructed before B, and you
can't ensure externally that it isn't, so you can't test your
defensive measures.
 
J

Jeff Schwab

James said:
James said:
On Mar 3, 5:09 pm, "(e-mail address removed)"
[...]
[concerning singletons...]
Like most things, they can be overused, but a few special cases
do occur to me. ...
I sometimes use it for command line options if I need to put
something together quickly (even then I try to keep the
command line data local to main and pass around the relevant
parts as needed),
Actually, I've found it preferable for individual components to
handle their own options, with no global specification of the
complete list of options anywhere. At least in a lot of cases.
How do you recognize bad options? Do the components register
their flags in a table somewhere? I also don't keep the
arguments around (except in argv)), but still find I have to
define them all in one place, e.g. in a getopt format string.

It depends on what makes them bad. If it's an unknown option,
of course, CommandLine doesn't find it registered when it
processes argc, argv, and complains (a fatal error). If it's a
problem with an argument to the option (supposing there is one),
that's up to the actual option to handle.

Of course, I still do have to define them all in one place: the
man page:). (With getopt, of course, I'd have to define them
there as well.)

If you're interested, the code is on line. Not the very latest
version, but these particular components haven't changed that
much. (Or have they? I know I added support for positional
dependent options at one point, things like the -l option of the
compiler. It may not be in the version currently on line.)

Are these the correct link and path?

http://kanze.james.neuf.fr/code-en.html
Util/Process/CommandLine
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,787
Messages
2,569,629
Members
45,332
Latest member
LeesaButts

Latest Threads

Top