Connecting Tech Pros Worldwide Forums | Help | Site Map

about the safety of auto_ptr<class T>

guru.slt@gmail.com
Guest
 
Posts: n/a
#1: Jul 23 '05
Hi,

see this code:

auto_ptr<int> int_auto_p(new int(3));
auto_ptr<int> int_auto_p2(int_auto_p.get());

Then, both auto_pointer will own the same object. That will violate the
single ownership expectation on auto_pointer.

Also, if i use this:

int * p = int_auot_p.get();
delete p;

Then, the object owned by auto_pointer will be removed from outside.
It's also not safe.

So, auto_pointer is not so safe.

any comments?


Howard
Guest
 
Posts: n/a
#2: Jul 23 '05

re: about the safety of auto_ptr<class T>



<guru.slt@gmail.com> wrote in message
news:1118854562.395131.94330@g47g2000cwa.googlegro ups.com...[color=blue]
> Hi,
>
> see this code:
>
> auto_ptr<int> int_auto_p(new int(3));
> auto_ptr<int> int_auto_p2(int_auto_p.get());
>
> Then, both auto_pointer will own the same object. That will violate the
> single ownership expectation on auto_pointer.
>
> Also, if i use this:
>
> int * p = int_auot_p.get();
> delete p;
>
> Then, the object owned by auto_pointer will be removed from outside.
> It's also not safe.
>
> So, auto_pointer is not so safe.
>
> any comments?
>[/color]

What safety are you expecting? The following isn't "safe", either:

int* p1 = new int(3);
int* p2 = p1;
delete p1;
// now, p2 points to deleted memory.

What you do externally with the internal pointer of an auto_ptr is not under
the control of the auto_ptr. How could it be? The only option would be to
prevent the use of get(), but that would hardly be a good solution, would
it?

Basically, if you do things you shouldn't do, you only have yourself to
blame. Don't blame the hammer because you hit your thumb!

-Howard


Pete Becker
Guest
 
Posts: n/a
#3: Jul 23 '05

re: about the safety of auto_ptr<class T>


guru.slt@gmail.com wrote:[color=blue]
>
> So, auto_pointer is not so safe.
>
> any comments?
>[/color]

Patient: "Doctor, it hurts when I do this."

Doctor: "So don't do that."

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)
Victor Bazarov
Guest
 
Posts: n/a
#4: Jul 23 '05

re: about the safety of auto_ptr<class T>


guru.slt@gmail.com wrote:
^^^^
What's the "slt" stand for?
[color=blue]
> see this code:
>
> auto_ptr<int> int_auto_p(new int(3));
> auto_ptr<int> int_auto_p2(int_auto_p.get());
>
> Then, both auto_pointer will own the same object. That will violate the
> single ownership expectation on auto_pointer.
>
> Also, if i use this:
>
> int * p = int_auot_p.get();
> delete p;
>
> Then, the object owned by auto_pointer will be removed from outside.
> It's also not safe.
>
> So, auto_pointer is not so safe.
>
> any comments?[/color]

If I climb on a chair and then jump on the cement floor head-first, I will
most likely injure myself, either permanently or fatally. So, neither the
chair nor the cement floor are safe. Hell, sitting and walking aren't
safe then since they involve the chair or the floor. Did you know that
living your life leads to your death with 100% certainty?

These are my comments.

V
Andre Kostur
Guest
 
Posts: n/a
#5: Jul 23 '05

re: about the safety of auto_ptr<class T>


"guru.slt@gmail.com" <guru.slt@gmail.com> wrote in
news:1118854562.395131.94330@g47g2000cwa.googlegro ups.com:
[color=blue]
> Hi,
>
> see this code:
>
> auto_ptr<int> int_auto_p(new int(3));
> auto_ptr<int> int_auto_p2(int_auto_p.get());[/color]

_You_ are breaking the constraints on the class. The pointer retrieved
by .get() is still owned by the first auto_ptr. It's _your_
responsibility to not delete it (even indirectly by feeding it to another
auto_ptr). After all, you have _specifically_ requested a pointer that
you _know_ is will still be controlled by the auto_ptr.
[color=blue]
> Then, both auto_pointer will own the same object. That will violate the
> single ownership expectation on auto_pointer.[/color]

Yep, you intentionally did it. I don't see a problem here (OK, except in
the person who wrote the code...).
[color=blue]
> Also, if i use this:
>
> int * p = int_auot_p.get();
> delete p;[/color]

Breaking the constraint again. The pointer retrieved by .get() is still
owned by the auto_ptr. It's your responsibility to not delete it. If
you really wanted to, use .release().
[color=blue]
> Then, the object owned by auto_pointer will be removed from outside.
> It's also not safe.
>
> So, auto_pointer is not so safe.[/color]

Skydiving isn't safe either when you cut your own parachute strings.
Neither is scuba diving if you block your air lines.
Howard
Guest
 
Posts: n/a
#6: Jul 23 '05

re: about the safety of auto_ptr<class T>



"Howard" <alicebt@hotmail.com> wrote in message
news:lpZre.963691$w62.138460@bgtnsc05-news.ops.worldnet.att.net...[color=blue]
>
> <guru.slt@gmail.com> wrote in message
> news:1118854562.395131.94330@g47g2000cwa.googlegro ups.com...[color=green]
>> Hi,
>>
>> see this code:
>>
>> auto_ptr<int> int_auto_p(new int(3));
>> auto_ptr<int> int_auto_p2(int_auto_p.get());
>>[/color][/color]

By the way, if you want to accomplish the above, try something like this:

auto_ptr<int> int_auto_p(new int(3));
auto_ptr<int> int_auto_p2(new int(*int_auto_p.get()));

I *think* I got the syntax right. The idea is to initialize a new int
pointer with the contents of the other guy's int pointer, instead of using
the other guy's int pointer directly.

-Howard


Victor Bazarov
Guest
 
Posts: n/a
#7: Jul 23 '05

re: about the safety of auto_ptr<class T>


Howard wrote:[color=blue]
> "Howard" <alicebt@hotmail.com> wrote in message
> news:lpZre.963691$w62.138460@bgtnsc05-news.ops.worldnet.att.net...
>[color=green]
>><guru.slt@gmail.com> wrote in message
>>news:1118854562.395131.94330@g47g2000cwa.googleg roups.com...
>>[color=darkred]
>>>Hi,
>>>
>>>see this code:
>>>
>>>auto_ptr<int> int_auto_p(new int(3));
>>>auto_ptr<int> int_auto_p2(int_auto_p.get());
>>>[/color][/color]
>
>
> By the way, if you want to accomplish the above, try something like this:
>
> auto_ptr<int> int_auto_p(new int(3));
> auto_ptr<int> int_auto_p2(new int(*int_auto_p.get()));
>
> I *think* I got the syntax right. The idea is to initialize a new int
> pointer with the contents of the other guy's int pointer, instead of using
> the other guy's int pointer directly.[/color]

I am not sure what the 'guru' wanted to accomplish there. Are you? Why
not simply do

auto_ptr<int> int_auto_p2(int_auto_p1);

which will transfer the ownership?...

V
Howard
Guest
 
Posts: n/a
#8: Jul 23 '05

re: about the safety of auto_ptr<class T>



"Victor Bazarov" <v.Abazarov@comAcast.net> wrote in message
news:0MZre.2548$Tf5.2387@newsread1.mlpsca01.us.to. verio.net...[color=blue]
> Howard wrote:[color=green]
>> "Howard" <alicebt@hotmail.com> wrote in message
>> news:lpZre.963691$w62.138460@bgtnsc05-news.ops.worldnet.att.net...
>>[color=darkred]
>>><guru.slt@gmail.com> wrote in message
>>>news:1118854562.395131.94330@g47g2000cwa.google groups.com...
>>>
>>>>Hi,
>>>>
>>>>see this code:
>>>>
>>>>auto_ptr<int> int_auto_p(new int(3));
>>>>auto_ptr<int> int_auto_p2(int_auto_p.get());
>>>>[/color]
>>
>>
>> By the way, if you want to accomplish the above, try something like this:
>>
>> auto_ptr<int> int_auto_p(new int(3));
>> auto_ptr<int> int_auto_p2(new int(*int_auto_p.get()));
>>
>> I *think* I got the syntax right. The idea is to initialize a new int
>> pointer with the contents of the other guy's int pointer, instead of
>> using the other guy's int pointer directly.[/color]
>
> I am not sure what the 'guru' wanted to accomplish there. Are you? Why
> not simply do
>
> auto_ptr<int> int_auto_p2(int_auto_p1);
>
> which will transfer the ownership?...
>
> V[/color]

You're right, I don't know really what he wanted to accomplish (if
anything). I made a guess.

-H



Phil Endecott
Guest
 
Posts: n/a
#9: Jul 23 '05

re: about the safety of auto_ptr<class T>


> auto_ptr<int> int_auto_p(new int(3));[color=blue]
> auto_ptr<int> int_auto_p2(int_auto_p.get());[/color]

I wonder what can be done to make this sort of code either look more
dangerous or to generate more warnings. I'm thinking of things like
reinterpret_cast<> which takes so long to type that by the time you've
got to the end of it you've been able to reflect on whether it's what
you really wanted to do or not. Other cases where you end up with a
dangling pointer can be picked up by the compiler, e.g. returning a
pointer to a local variable. Is there anything that the compiler or
library implementation can do to discourage people from doing stupid
things like this? (I hope people agree that, in general, compiler
warnings are good things.)

--Phil.

guru.slt@gmail.com
Guest
 
Posts: n/a
#10: Jul 23 '05

re: about the safety of auto_ptr<class T>


i want to show:

1). auto_ptr is not so safe.
2). given 1) is true, then it seems no much reason to use auto_ptr,
because we can use normal pointer safely, with care.

in this respect, auto_ptr does not have much obvious advantage over
normal pointer.

Howard Hinnant
Guest
 
Posts: n/a
#11: Jul 23 '05

re: about the safety of auto_ptr<class T>


In article <1118854562.395131.94330@g47g2000cwa.googlegroups. com>,
"guru.slt@gmail.com" <guru.slt@gmail.com> wrote:
[color=blue]
> Hi,
>
> see this code:
>
> auto_ptr<int> int_auto_p(new int(3));
> auto_ptr<int> int_auto_p2(int_auto_p.get());
>
> Then, both auto_pointer will own the same object. That will violate the
> single ownership expectation on auto_pointer.
>
> Also, if i use this:
>
> int * p = int_auot_p.get();
> delete p;
>
> Then, the object owned by auto_pointer will be removed from outside.
> It's also not safe.
>
> So, auto_pointer is not so safe.
>
> any comments?[/color]

In addition to other's comments...

Very few (any?) C++ library components are designed to prevent
intentional abuse, but good ones _do_ prevent accidental abuse. And the
examples you give seem like they would be hard to code by accident.
Yes, use of get() is dangerous. So use it wisely. And if you're not
sure where you've used it, it is easy to search for.

That being said, I do consider auto_ptr dangerous because it does lead
to accidental abuse. Consider:

template <class Iter>
void foo(Iter begin, Iter end)
{
typedef typename std::iterator_traits<Iter>::value_type T;
for (Iter i = begin; i != end; ++i)
{
T temp = *i;
// ...
// operate on [begin, end) using temp
// ...
}
}

This is reasonable generic code. Indeed some implementations of
std::sort have been coded this way. Now consider what happens when T
turns out to be auto_ptr.

The statement:

T temp = *i;

/moves/ not copies from the range to the local, leaving a "hole" in the
range. If the generic algorithm does not later fill that hole and
eventually move the local temp back into the range - all in a fashion
that does not invalidate the algorithm's logic, then use of sequences of
auto_ptr with this generic code will silently create run time errors.

The problem lies not with the generic code "foo", but with auto_ptr's
design of moving with copy syntax (from lvalues). So avoid use of
auto_ptr with generic code if you can. And if you can't, ensure that
the generic code can handle the "moves with copy syntax" behavior.

-Howard
Victor Bazarov
Guest
 
Posts: n/a
#12: Jul 23 '05

re: about the safety of auto_ptr<class T>


guru.slt@gmail.com wrote:[color=blue]
> i want to show:
>
> 1). auto_ptr is not so safe.
> 2). given 1) is true, then it seems no much reason to use auto_ptr,
> because we can use normal pointer safely, with care.[/color]
^^^^^^^^^
Isn't that the key word here?
[color=blue]
> in this respect, auto_ptr does not have much obvious advantage over
> normal pointer.[/color]

Yes, it does. You need much less "care" with std::auto_ptr than you
would with a regular pointer. A simple transfer of the ownership on
copy-construction and assignment is the _major_ advantage.

V
Pete Becker
Guest
 
Posts: n/a
#13: Jul 23 '05

re: about the safety of auto_ptr<class T>


guru.slt@gmail.com wrote:[color=blue]
> i want to show:
>
> 1). auto_ptr is not so safe.
> 2). given 1) is true, then it seems no much reason to use auto_ptr,
> because we can use normal pointer safely, with care.
>
> in this respect, auto_ptr does not have much obvious advantage over
> normal pointer.
>[/color]

auto_ptr's primary purpose is to insure that an allocated resource is
destroyed if an exception is thrown. That's much harder to do with an
ordinary pointer.

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)
Howard Hinnant
Guest
 
Posts: n/a
#14: Jul 23 '05

re: about the safety of auto_ptr<class T>


In article <1118858704.006478.187620@g47g2000cwa.googlegroups .com>,
"guru.slt@gmail.com" <guru.slt@gmail.com> wrote:
[color=blue]
> i want to show:
>
> 1). auto_ptr is not so safe.
> 2). given 1) is true, then it seems no much reason to use auto_ptr,
> because we can use normal pointer safely, with care.
>
> in this respect, auto_ptr does not have much obvious advantage over
> normal pointer.[/color]

Despite its dangers, auto_ptr can be used to help create exception safe
code much easier (and more efficiently, depending upon the platform)
than can be done with pointers.

For example this:

// foo is responsible for deleting p
void foo(int* p)
{
auto_ptr<int> ap(p);
// do things here that might throw an exception
}

is superior to this:

// foo is responsible for deleting p
void foo(int* p)
{
try
{
// do things here that might throw an exception
delete p;
}
catch (...)
{
delete p;
throw;
}
}

The latter is more prone to coding errors, and does not scale well the
number of resources that need to be cleaned up.

-Howard
Pete Becker
Guest
 
Posts: n/a
#15: Jul 23 '05

re: about the safety of auto_ptr<class T>


Howard Hinnant wrote:
[color=blue]
>
> The problem lies not with the generic code "foo", but with auto_ptr's
> design of moving with copy syntax (from lvalues).[/color]

The problem lies with creating sequences of auto_ptr objects. That's
never a good idea, and it's the reason that auto_ptr objects can't be
put into standard containers.
[color=blue]
> So avoid use of
> auto_ptr with generic code if you can.[/color]

And you should always make sure that you can. <g>

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)
Steven T. Hatton
Guest
 
Posts: n/a
#16: Jul 23 '05

re: about the safety of auto_ptr<class T>


guru.slt@gmail.com wrote:
[color=blue]
> Hi,
>
> see this code:
>
> auto_ptr<int> int_auto_p(new int(3));
> auto_ptr<int> int_auto_p2(int_auto_p.get());
>
> Then, both auto_pointer will own the same object. That will violate the
> single ownership expectation on auto_pointer.
>
> Also, if i use this:
>
> int * p = int_auot_p.get();
> delete p;
>
> Then, the object owned by auto_pointer will be removed from outside.
> It's also not safe.
>
> So, auto_pointer is not so safe.
>
> any comments?[/color]

One approach I've seen to the general problem of managing dynamically
created objects is to create a reference counted type and an associated
pointer type that increments and decrements the reference as it is created,
assigned to, or destroyed. One example is the osg::Referenced, and the
associated osg::ref_ptr.

http://www.openscenegraph.org/documentation/

That served as much of the motivation for the code I recently posted using
the boost::intrusive_ptr<> template. There are some restrictions on how
instances of the reference counted class can be used. My class is more
restrictive than the one provied by OSG. In both cases, the destructor for
the reference counted class and all of its derivatives is protected, and
can only be accessed by a friend, or a derived class. This means objects
of this type cannot be used as automatic variables since there is an
implicit call to the destructor when the variable goes out of scope. In
the case of OSG, the osg::Referenced class makes the ref() and unref()
member functions public, thus permitting ad hoc modification of reference
counts. In the case of my util::Referenced, this is not an option. The
only way to manipulate the reference counts is through the

util::intrusive_ptr_add_ref
util::intrusive_ptr_release

I would prefer these not be publicly available, but do not see a way round
the fact that they are. In either case, the only way to destroy an object
derived from the reference counted baseclass is to decrement the reference
to 0.

This is not a perfect approach in that it leads to aforementioned
restrictions on the reference counted objects. Until the user becomes
familiar with the idiosyncracies of these classes they can be rather
difficult to work with.
--
If our hypothesis is about anything and not about some one or more
particular things, then our deductions constitute mathematics. Thus
mathematics may be defined as the subject in which we never know what we
are talking about, nor whether what we are saying is true.-Bertrand Russell
Howard
Guest
 
Posts: n/a
#17: Jul 23 '05

re: about the safety of auto_ptr<class T>



<guru.slt@gmail.com> wrote in message
news:1118858704.006478.187620@g47g2000cwa.googlegr oups.com...[color=blue]
>i want to show:
>
> 1). auto_ptr is not so safe.
> 2). given 1) is true, then it seems no much reason to use auto_ptr,
> because we can use normal pointer safely, with care.
>
> in this respect, auto_ptr does not have much obvious advantage over
> normal pointer.
>[/color]

All of C++ is "not safe", if you use it incorrectly. So I guess that means
that you shouldn't use it, because you can do the same thing with, say,
pencil and paper?

You're simply using auto_ptr incorrectly. You're granting ownership of
someone else's pointer, which is not how it's intended to be used.

We really don't care whether you use auto_ptr or not, but your inability to
understand how to use it correctly is no reason for anyone else to avoid
using it. I'd strongly advise you to learn what that tool is really for
(research "resource acquisition is initialization").

-Howard


Howard Hinnant
Guest
 
Posts: n/a
#18: Jul 23 '05

re: about the safety of auto_ptr<class T>


In article <aYOdnREycKBK7S3fRVn-1g@rcn.net>,
Pete Becker <petebecker@acm.org> wrote:
[color=blue]
> Howard Hinnant wrote:
>[color=green]
> >
> > The problem lies not with the generic code "foo", but with auto_ptr's
> > design of moving with copy syntax (from lvalues).[/color]
>
> The problem lies with creating sequences of auto_ptr objects. That's
> never a good idea, and it's the reason that auto_ptr objects can't be
> put into standard containers.[/color]

Despite the ban on std::container<auto_ptr<T>>, clients can still do:

non_std::container<auto_ptr<T>>

and even simply:

auto_ptr<T> my_dangerous_array[n];

Furthermore, simply banning sequences of auto_ptr isn't sufficient for
safety. You must still avoid generic code which uses auto_ptr, unless
you can determine that the generic code is "auto_ptr safe":

namespace detail
{

template <class T>
void bar(T t);

}

template <class T>
void foo(T& t)
{
...
detail::bar(t);
...
}

Will the client of foo<auto_ptr<T>> realize that control of the pointer
is going to be acquired by foo, even though foo takes its parameter by
non-const ref? The author of foo<T> has no motivation to document that
foo calls bar as an implementation detail.

-Howard
Pete Becker
Guest
 
Posts: n/a
#19: Jul 23 '05

re: about the safety of auto_ptr<class T>


Howard Hinnant wrote:[color=blue]
> In article <aYOdnREycKBK7S3fRVn-1g@rcn.net>,
> Pete Becker <petebecker@acm.org> wrote:
>
>[color=green]
>>Howard Hinnant wrote:
>>
>>[color=darkred]
>>>The problem lies not with the generic code "foo", but with auto_ptr's
>>>design of moving with copy syntax (from lvalues).[/color]
>>
>>The problem lies with creating sequences of auto_ptr objects. That's
>>never a good idea, and it's the reason that auto_ptr objects can't be
>>put into standard containers.[/color]
>
>
> Despite the ban on std::container<auto_ptr<T>>, clients can still do:
>
> non_std::container<auto_ptr<T>>[/color]

Yes, of course they can. They shouldn't do it, for the same reason that
they shouldn't create standard containers holding auto_ptr objects: they
won't work right.
[color=blue]
>
> and even simply:
>
> auto_ptr<T> my_dangerous_array[n];
>
> Furthermore, simply banning sequences of auto_ptr isn't sufficient for
> safety.[/color]

I wasn't talking about banning anything, just pointing out what the
problem in the example you gave is.
[color=blue]
> You must still avoid generic code which uses auto_ptr, unless
> you can determine that the generic code is "auto_ptr safe":[/color]

Yes, auto_ptr has to be used carefully.

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)
Andre Kostur
Guest
 
Posts: n/a
#20: Jul 23 '05

re: about the safety of auto_ptr<class T>


"guru.slt@gmail.com" <guru.slt@gmail.com> wrote in
news:1118858704.006478.187620@g47g2000cwa.googlegr oups.com:
[color=blue]
> i want to show:
>
> 1). auto_ptr is not so safe.
> 2). given 1) is true, then it seems no much reason to use auto_ptr,
> because we can use normal pointer safely, with care.
>
> in this respect, auto_ptr does not have much obvious advantage over
> normal pointer.
>[/color]

1) You failed. It is no less safe than a naked pointer, and has certain
advantages.
2) Given a false premise, you cannot draw any conclusions from it.
Panjandrum
Guest
 
Posts: n/a
#21: Jul 23 '05

re: about the safety of auto_ptr<class T>


guru.slt@gmail.com wrote:[color=blue]
> i want to show:
>
> 1). auto_ptr is not so safe.
> 2). given 1) is true, then it seems no much reason to use auto_ptr,
> because we can use normal pointer safely, with care.
>
> in this respect, auto_ptr does not have much obvious advantage over
> normal pointer.[/color]

It also has many disadvantages and usability traps. And, most of all,
auto_ptr is not a pointer. Just an object that implements an
operator*() function.

Victor Bazarov
Guest
 
Posts: n/a
#22: Jul 23 '05

re: about the safety of auto_ptr<class T>


Panjandrum wrote:[color=blue]
> guru.slt@gmail.com wrote:[color=green]
>> i want to show:
>>
>> 1). auto_ptr is not so safe.
>> 2). given 1) is true, then it seems no much reason to use auto_ptr,
>> because we can use normal pointer safely, with care.
>>
>> in this respect, auto_ptr does not have much obvious advantage over
>> normal pointer.[/color]
>
> It also has many disadvantages and usability traps. And, most of all,
> auto_ptr is not a pointer. Just an object that implements an
> operator*() function.[/color]

.... and the operator->() function ... and very specific copying ...


red floyd
Guest
 
Posts: n/a
#23: Jul 23 '05

re: about the safety of auto_ptr<class T>


Victor Bazarov wrote:[color=blue]
> Panjandrum wrote:
>[color=green]
>>guru.slt@gmail.com wrote:
>>[color=darkred]
>>>i want to show:
>>>
>>>1). auto_ptr is not so safe.
>>>2). given 1) is true, then it seems no much reason to use auto_ptr,
>>>because we can use normal pointer safely, with care.
>>>
>>>in this respect, auto_ptr does not have much obvious advantage over
>>>normal pointer.[/color]
>>
>>It also has many disadvantages and usability traps. And, most of all,
>>auto_ptr is not a pointer. Just an object that implements an
>>operator*() function.[/color]
>
>
> ... and the operator->() function ... and very specific copying ...
>
>[/color]

I use auto_ptr quite often, and use it for for specific purposes.
If I could, I'd use a local object, but I'm creating from a factory for
polymorphic behaviour.

i.e.

class Base { ... };
Base* CreateMemberOfBaseFamily(const std:string&);

void f()
{
std::string s;


// read s from some input source


std::auto_ptr pBase(CreateMemberOfBaseFamily(s));
// do stuff with pBase here, that includes the
// possibility of exceptions!!!!

// I don't have to worry about deleting pBase here,
// and I don't have to worry about catching any
// and all exceptions, because pBase will be cleaned
// up automatically
}
Steven T. Hatton
Guest
 
Posts: n/a
#24: Jul 23 '05

re: about the safety of auto_ptr<class T>


http://www.kangaroologic.com/interfa...nique_ptr.html
http://tinyurl.com/aat8r
--
If our hypothesis is about anything and not about some one or more
particular things, then our deductions constitute mathematics. Thus
mathematics may be defined as the subject in which we never know what we
are talking about, nor whether what we are saying is true.-Bertrand Russell
Closed Thread