Quick question on smart pointers

S

Susan Baker

Hi,

I'm just reading about smart pointers..
I have some existing C code that I would like to provide wrapper classes
for. Specifically, I would like to provide wrappers for two stucts
defined as ff:

typedef struct {
float *data ;
int count ;
} series ;

typedef struct {
void *clientdata ;
FUNC_PTR1 cb1 ;
FUNC_PTR2 cb2 ;
struct param_ pdata ;
int size ;
} client


I am thinking of providing a wrapper for the first one as ff:

class Series {
std::auto_pointer<series> sPtr ;
....
}

Couple of quick questions:

1). Can I do this (I probably should have checked to see if it would
compile first)
2). From my understanding of auto_ptr, variable sPtr gets freed
automagically when class Series goes out of scope (I can't imagine how
this is possible)
3). Will the responses for the previous two statements hold true for a
more complicated structure like client above?

Thanks
 
K

Karl Heinz Buchegger

Susan said:
Hi,

I'm just reading about smart pointers..
I have some existing C code that I would like to provide wrapper classes
for. Specifically, I would like to provide wrappers for two stucts
defined as ff:

typedef struct {
float *data ;
int count ;
} series ;

typedef struct {
void *clientdata ;
FUNC_PTR1 cb1 ;
FUNC_PTR2 cb2 ;
struct param_ pdata ;
int size ;
} client

I am thinking of providing a wrapper for the first one as ff:

class Series {
std::auto_pointer<series> sPtr ;
....
}

Well, You could do that. But it would probably be easier to change it to

typedef std::vector< float > Series;

cause the whole structure looks extremely like the C way to code a dynamicaly
resizable array.
Couple of quick questions:

1). Can I do this (I probably should have checked to see if it would
compile first)

You can do it.
But I recommend to first take a step back and ask a question: "What is the purpose
of that struct?" and "Is there a common C++ method to achieve that purpose?"
2). From my understanding of auto_ptr, variable sPtr gets freed
automagically when class Series goes out of scope (I can't imagine how
this is possible)

It is done easily:
A std::auto_ptr is an object like any other object. When it goes out of scope, its
destructor is called. And now guess what that destructor does.
3). Will the responses for the previous two statements hold true for a
more complicated structure like client above?

You are looking for a cook book recipe. I don't think you will find one.
This is what makes programming sometimes frustrating but on the other hand
this is what makes programming interesting: "One size fits all" does seldome
apply in programming.
 
P

Panjandrum

I am thinking of providing a wrapper for the first one as ff:
class Series {
std::auto_pointer<series> sPtr ;
....
}

This is very error prone. Consider:

Series s1;
Series s2 = s1; //!!!
Couple of quick questions:

1). Can I do this (I probably should have checked to see if it would
compile first)

Do you really want/need to use a smart pointer? Just use plain RAII
with private copy constructor and assingment operator.
2). From my understanding of auto_ptr, variable sPtr gets freed
automagically when class Series goes out of scope (I can't imagine how
this is possible)

The magic is called destructor (it's magic only for Java programmers).
3). Will the responses for the previous two statements hold true for a
more complicated structure like client above?

If you maintain the 'creator is deleter' rule many 'problems' disappear
in C++.
 
T

Torsten Mueller

Susan Baker said:
typedef struct {
float *data ;
int count ;
} series ;

typedef struct {
void *clientdata ;
FUNC_PTR1 cb1 ;
FUNC_PTR2 cb2 ;
struct param_ pdata ;
int size ;
} client

I am thinking of providing a wrapper for the first one as ff:

class Series {
std::auto_pointer<series> sPtr ;
....
}

I don't understand what you are planning. Why not use a real class
instead of the series struct? What should the auto_ptr do here?

I suggest not to use this auto_ptr stuff. This is for people who's
right hand doesn't know what the left hand is doing. You can always
have a simple pointer in your class and delete it yourself. This is
what destructors are made for.

T.M.
 
S

sugary.boy

typedef struct {
float *data ;
int count ;



} series ;

I am wondering as, what is the play of this count variable in
struct?...If it is counting number of object instanciated then better
make it static.
 
G

Geo

Torsten said:
I don't understand what you are planning. Why not use a real class
instead of the series struct? What should the auto_ptr do here?

I suggest not to use this auto_ptr stuff. This is for people who's
right hand doesn't know what the left hand is doing. You can always
have a simple pointer in your class and delete it yourself. This is
what destructors are made for.

T.M.

Surely auto_ptr is the last thing to use if you don't know what you're
doing ??
 
S

Susan Baker

Panjandrum said:
This is very error prone. Consider:

Series s1;
Series s2 = s1; //!!!




Do you really want/need to use a smart pointer? Just use plain RAII
with private copy constructor and assingment operator.




The magic is called destructor (it's magic only for Java programmers).
The "magic" I was referring to (which everyone seems to have missed -
perhaps I did not make my self clear enough) was this: how can
auto_pointer correctly free memory allocated for a complicated structure
like client - which has several pointer members. It is my feeling that I
am misinterpreting the use(abuse?) of the auto_pointer and I just needed
some clarification on this point. The way I see it, using auto_pointer
in this way will lead to serious memory leaks - unless the container is
made aware of the details of the object (struct in this case), that it
is acting as a container of. This is what I mean when I say I cannot
imagine how the container finds out how to free the appropriate pointers
in the structure. The more I think abot it, the more it seems like I got
the wrong end of the stick. I don't think auto_pointers can be used this
way without memory leaks (although
http://www.parashift.com/c++-faq-lite/exceptions.html#faq-17.4 appears
to suggest just that). I'll have to take another read to be sure....

If you maintain the 'creator is deleter' rule many 'problems' disappear
in C++.

True - but then what is the point of the container?. I *thought* the
container was "managing" mem resources for me - I can just as quickly
roll my own "container" using an array. What "exactly" makes it a "safe
pointer".
 
B

bart.kowalski

I suggest not to use this auto_ptr stuff. This is for people who's
That's just not true. If you want your code to be exception safe then
naked pointers are very tricky. It's unfortunate that the majority of
the C++ crowd doesn't think this way but smart pointers (not
necessarily std::auto_ptr) should be used instead of naked pointer
unless there's a good reason not to, NOT the other way around.
 
S

Susan Baker

That's just not true. If you want your code to be exception safe then
naked pointers are very tricky. It's unfortunate that the majority of
the C++ crowd doesn't think this way but smart pointers (not
necessarily std::auto_ptr) should be used instead of naked pointer
unless there's a good reason not to, NOT the other way around.

So briefly, what do they buy me over and above naked pointers?, and how
may I use them in the example stucture I provided previously? (using the
simpler struct "series" as an example - if you please).

Thanks
 
K

kartoffelsack

Am Wed, 06 Jul 2005 13:32:36 +0200 schrieb Susan Baker
Hi,

I'm just reading about smart pointers..
I have some existing C code that I would like to provide wrapper classes
for. Specifically, I would like to provide wrappers for two stucts
defined as ff:

typedef struct {
float *data ;
int count ;
} series ;

typedef struct {
void *clientdata ;
FUNC_PTR1 cb1 ;
FUNC_PTR2 cb2 ;
struct param_ pdata ;
int size ;
} client


I am thinking of providing a wrapper for the first one as ff:

class Series {
std::auto_pointer<series> sPtr ;
....
}

Couple of quick questions:

1). Can I do this (I probably should have checked to see if it would
compile first)
Yes

2). From my understanding of auto_ptr, variable sPtr gets freed
automagically when class Series goes out of scope (I can't imagine how
this is possible)

The auto_ptr-Object is a 'normal' object on the stack. When it get's out
of scope it's destructor gets called. The dtor deletes the owned object
3). Will the responses for the previous two statements hold true for a
more complicated structure like client above?

Yes. But be aware the ownership-policy of auto_ptr. The ownership of the
pointer is passed, if the auto_ptr gets copied. The other forgets about
the pointer. Thus, one pointer belongs allways to exactly one auto_ptr. So
auto_ptr is in common not helpful if you want to copy your
wrapper-classes. If so, use boost/shared_ptr (www.boost.org)
 
T

Torsten Mueller

Geo said:
Surely auto_ptr is the last thing to use if you don't know what
you're doing ??

No, for a reason I don't know it's the first thing.

T.M.
 
T

Torsten Mueller

If you want your code to be exception safe then naked pointers are
very tricky.

It's not. But you simply must know what you do.

Indeed proponents of the auto_ptr template [1] are just too lazy to
think about a concept in their program. They just want to use an
object and don't want to waste any time with its allocation and
deallocation. Oftenly they are students, having not much time, knowing
just the Java world from their university and blaming C++ for bad
memory management. Normally this leads to sources I find complicated
to read because of an additional layer of indirection.
It's unfortunate that the majority of the C++ crowd doesn't think
this way but smart pointers (not necessarily std::auto_ptr) should
be used instead of naked pointer unless there's a good reason not
to, NOT the other way around.

But why? This is like driving a car with a helmet.

In the last 15 years I used exactly one smart pointer, and this one
had reference counting and methods for exchanging the inner object by
another ... I had never the idea of automatic memory management even
in my large applications. And I'm an extremist in asking for
prevention of memory leaks.

T.M.

[1] I don't mean smart pointers with reference counting, I mean just
such primitive smart pointers like auto_ptr.
 
K

Karl Heinz Buchegger

Susan said:
The "magic" I was referring to (which everyone seems to have missed -
perhaps I did not make my self clear enough) was this: how can
auto_pointer correctly free memory allocated for a complicated structure
like client - which has several pointer members.

And the answer is: it can't

typedef struct {
void *clientdata ;
FUNC_PTR1 cb1 ;
FUNC_PTR2 cb2 ;
struct param_ pdata ;
int size ;
} client;

You are talking about having an auto_ptr (or some other smart pointer)
to a client object. Well, the only thing the smart pointer does, is
to keep track of when the client object itself should be destroyed.
It is the job of the client object to take care of its inner details.
It does this by eg. making all the pointers in the client struct smart
pointers by themselfs or to simply do the delete in the destructor.
The smart pointer cares about the client object as a whole. The client
object is repsonsible for the inner details of itself.
True - but then what is the point of the container?.

To have one object that is reponsible for all the data in it.
I *thought* the
container was "managing" mem resources for me - I can just as quickly
roll my own "container" using an array.

Yes. Then the array *is* your container. No problem with that.
But don't roll your own. Use what is already available.
What "exactly" makes it a "safe
pointer".

A safe pointer, or what we call a smart pointer, *ensures* that the delete
is executed. Even if you, the programmer have long forgotten that something
was dynamically allocated. It does this delete in all cases by the shear fact
that the smart pointer object is itself destroyed in some way. Be it that the
smart pointer is a member of some structure and an object of that structure
is allocated as a local variable and goes out of scope. Or that this structure
object is dynamically allocated and gets deleted.
There is no magic in it. Everything can be done 'by hand' also. The only problem
is, that humans tend to make mistakes and forget to do things. Then it is handy
to have an object that does the cleanup all by itself without the programmer having
to do anything except just using that smart pointer instead of an ordinary pointer.
 
B

bart.kowalski

Torsten said:
If you want your code to be exception safe then naked pointers are
very tricky.

It's not. But you simply must know what you do.

Indeed proponents of the auto_ptr template [1] are just too lazy to
think about a concept in their program. They just want to use an
object and don't want to waste any time with its allocation and
deallocation. Oftenly they are students, having not much time, knowing
just the Java world from their university and blaming C++ for bad
memory management.

That is a VERY presumptious statement. I come from a C background and
have been working in C++ for several years, and I'm the one to tell you
that. For SOME people what you're saying may be true, but if you ask
experienced C++ programmers (such as the people in c.l.c++.moderated)
you'll see a very different picture.
Normally this leads to sources I find complicated
to read because of an additional layer of indirection.

Consider:

class Foo
{
Bar* a;
Bar* b;
};

void Foo::Init()
{
a = new Bar;
b = new Bar;
}

But what if b's ctor throws an exception? You have a potential memory
leak right there. You have to write:

void Foo::Init()
{
try
{
a = new Bar;
b = new Bar;
}
catch(...)
{
delete a;
delete b;
throw;
}
}

Are you going to write the above code every time you need two or more
dynamic resources? Frankly, I think using some kind of smart pointer is
both shorter and more reliable. Note that I said SOME KIND of smart
pointer. I'm not necessarily advocating std::auto_ptr, only some kind
of management class that wraps just one pointer and provides some form
of access to it.
But why? This is like driving a car with a helmet.

Smart pointers are not about protecting lazy programmers but about
what's more practical. C++ is meant to be a practical language, and I
find smart pointers to be more practical than raw pointers. That's the
bottom line.
 
B

bart.kowalski

Susan said:
So briefly, what do they buy me over and above naked pointers?, and how
may I use them in the example stucture I provided previously? (using the
simpler struct "series" as an example - if you please).

I'm not saying that you should use smart pointers in your example. I'm
just saying that whenever pointers are appropriate for the task at hand
then you should use smart pointers. In your case pointers are not even
appropriate for the task at hand.

Bart.
 
T

Torsten Mueller

C++ is meant to be a practical language,

Yes, of course!
and I find smart pointers to be more practical than raw pointers.

I do not. That's the difference.

Sorry, perhaps I've just seen too many young programmers becoming
frustrated because of a serious memory problem in their own absolutely
safe smart pointer world, because they (or anybody else!) forgot
somewhere to use a smart pointer where he should use one and then they
soon begin to blame C++ for causing daylong debugging sessions in
their safe programs.

T.M.
 
P

Panjandrum

Consider:

class Foo
{
Bar* a;
Bar* b;
};

void Foo::Init()
{
a = new Bar;
b = new Bar;
}

But what if b's ctor throws an exception? You have a potential memory
leak right there. You have to write:

void Foo::Init()
{
try
{
a = new Bar;
b = new Bar;
}
catch(...)
{
delete a;
delete b;
throw;
}
}

Are you going to write the above code every time you need two or more
dynamic resources?

No, alone because your code contains at least 1 bug. BTW, dumb pointers
objects (misleadingly called smart pointers) are not the only and not
the best way to use RAII.
 
K

Karl Heinz Buchegger

[snip]
But what if b's ctor throws an exception? You have a potential memory
leak right there. You have to write:

void Foo::Init()
{
try
{
a = new Bar;
b = new Bar;
}
catch(...)
{
delete a;
delete b;
throw;
}
}

Note that this is not the end of the story.
The above code still has a problem: What happens, when a's ctor throws
an exception? Then the catch will try to delete b through an uninitialzed pointer.
As you correctly say, at the moment you have more then 1 pointer things
can get tricky.
 
B

bart.kowalski

Karl said:
[snip]
But what if b's ctor throws an exception? You have a potential memory
leak right there. You have to write:

void Foo::Init()
{
try
{
a = new Bar;
b = new Bar;
}
catch(...)
{
delete a;
delete b;
throw;
}
}

Note that this is not the end of the story.
The above code still has a problem: What happens, when a's ctor throws
an exception? Then the catch will try to delete b through an uninitialzed pointer.

Ah, yes. I forgot how picky the people in this newsgroup can get
(haven't been here in a long while). Obviously, this example is not
complete. I'm assuming all pointers are null initialized, which is what
I always do in my code.
 

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,744
Messages
2,569,484
Members
44,906
Latest member
SkinfixSkintag

Latest Threads

Top