Discussion:
auto_ptr as a function argument
(too old to reply)
Kiwi
2005-04-07 11:08:08 UTC
Permalink
I am passing fromURL as shown below
bool WebStuff::AccessInternet(AnsiString sURL, TStringList *fromURL)


Remy introduced me to auto_ptrs and I was wondering how to pass an auto_ptr
as an argument in a function


I tried doing:

std::auto_ptr<TStringList> fromURL(new TStringList);

bool WebStuff::AccessInternet(AnsiString sURL, const
std::auto_ptr<TStringList> &fromURL)

but fromURL doesn't get passed properly.

I suspect there is a way to pass an auto_ptr as a function argument, I have
seen some relevant references
but I don't understand what I read.

Any help on the pros, cons, and mechanism for passing auto_ptrs as function
arguments would be much appreciated.

Thanks,
Kiwi
Hans Galema
2005-04-07 12:01:25 UTC
Permalink
Post by Kiwi
I am passing fromURL as shown below
bool WebStuff::AccessInternet(AnsiString sURL, TStringList *fromURL)
std::auto_ptr<TStringList> fromURL(new TStringList);
bool WebStuff::AccessInternet(AnsiString sURL, const
std::auto_ptr<TStringList> &fromURL)
Why would you do that ?

bool WebStuff::AccessInternet(AnsiString sURL, TStringList *fromURL)

would do. Why would AccessInternet() have to know that fromURL
has something to do with an auto_ptr ?
Post by Kiwi
but fromURL doesn't get passed properly.
Please be more exact.
Post by Kiwi
I suspect there is a way to pass an auto_ptr as a function argument,
Yes. All that you need is:

bool WebStuff::AccessInternet(AnsiString sURL, TStringList *fromURL);

std::auto_ptr<TStringList> fromURL(new TStringList);

And to call:

WebStuff1->AccessInternet( sURL, fromURL);
Post by Kiwi
Any help on the pros, cons, and mechanism for passing auto_ptrs as function
arguments would be much appreciated.
I showed you already. What do you want to accomplish ?

Hans.
Kiwi
2005-04-07 12:47:43 UTC
Permalink
Post by Hans Galema
Post by Kiwi
bool WebStuff::AccessInternet(AnsiString sURL, const
std::auto_ptr<TStringList> &fromURL)
Why would you do that ?
Because it seemed like a good idea similar since auto_ptrs are supposed to
easy memory management.
My implementation is similar to what I read somewhere that said passing by
reference works, obviously not similar enough because it doesn't work.
Post by Hans Galema
bool WebStuff::AccessInternet(AnsiString sURL, TStringList *fromURL)
would do. Why would AccessInternet() have to know that fromURL
has something to do with an auto_ptr ?
The C++ Builder (Personal Edition) seems to think it is important because it
won't compile, instead providing:

[C++ Error] WebStuff.cpp(251): E2034 Cannot convert 'auto_ptr<TStringList>
(*)(TStringList)' to 'TStringList *'
Post by Hans Galema
Post by Kiwi
but fromURL doesn't get passed properly.
Please be more exact.
Since bool WebStuff::AccessInternet(AnsiString sURL, TStringList *fromURL)
wouldn't compile with
std::auto_ptr<TStringList> fromURL(TStringList) and

bool WebStuff::AccessInternet(AnsiString sURL, const
std::auto_ptr<TStringList> &fromURL)

did but still didn't work I followed through "fromURL" which didn't change
the mouseover during debug showed fromURL{ }
only, it wasn't even filled with the usual NULL stuff.

Thanks, I hope this is more clear
Kiwi
Hans Galema
2005-04-07 13:06:27 UTC
Permalink
Post by Kiwi
The C++ Builder (Personal Edition) seems to think it is important because it
[C++ Error] WebStuff.cpp(251): E2034 Cannot convert 'auto_ptr<TStringList>
(*)(TStringList)' to 'TStringList *'
You are right. Sorry for my ignorance. I get the same result.

Well ....

Apparently one has to do:

#include <memory>
bool TForm1::AccessInternet(AnsiString sURL, std::auto_ptr<TStringList>fromURL)
{
ShowMessage ( fromURL->Text );
}

or

bool TForm1::AccessInternet(AnsiString sURL, std::auto_ptr<TStringList>& fromURL)
{
ShowMessage ( fromURL->Text );
}


void __fastcall TForm1::Button1Click(TObject *Sender)
{
std::auto_ptr<TStringList> fromURL(new TStringList);

fromURL->Add ( "First Line");
fromURL->Add ( "Second Line");

AccessInternet( "My URL", fromURL );
}

both work for me. bcb5.

Hans.
Kiwi
2005-04-07 13:47:45 UTC
Permalink
Please don't apologize, I wish I knew 10% of what some of you guys seem to
know.



This first one compiles for me but doesn't work, I still believe that an
auto_ptr needs to be passed
as a reference.
Post by Hans Galema
#include <memory>
bool TForm1::AccessInternet(AnsiString sURL,
std::auto_ptr<TStringList>fromURL)
{
ShowMessage ( fromURL->Text );
}
For some reason this now works for me too!
Post by Hans Galema
bool TForm1::AccessInternet(AnsiString sURL, std::auto_ptr<TStringList>& fromURL)
{
ShowMessage ( fromURL->Text );
}
Thanks for your help,
Kiwi
Chris Uzdavinis (TeamB)
2005-04-07 14:09:25 UTC
Permalink
Post by Kiwi
Post by Hans Galema
Post by Kiwi
bool WebStuff::AccessInternet(AnsiString sURL, const
std::auto_ptr<TStringList> &fromURL)
Why would you do that ?
Because it seemed like a good idea similar since auto_ptrs are supposed to
easy memory management.
My implementation is similar to what I read somewhere that said passing by
reference works, obviously not similar enough because it doesn't work.
Post by Hans Galema
bool WebStuff::AccessInternet(AnsiString sURL, TStringList *fromURL)
would do. Why would AccessInternet() have to know that fromURL
has something to do with an auto_ptr ?
The C++ Builder (Personal Edition) seems to think it is important because it
[C++ Error] WebStuff.cpp(251): E2034 Cannot convert 'auto_ptr<TStringList>
(*)(TStringList)' to 'TStringList *'
You'd want the caller to do something like this:

std::auto_ptr<TStringList> tsl( some_stringlist_ptr );

WebStuff * ws = get_webstuff();

ws->AccessInternet(url, tsl.get()); // auto_ptr::get() converts to raw ptr

// NOTE: auto_ptr still owns the object that was passed into AccessInternet!
--
Chris (TeamB);
Chris Uzdavinis (TeamB)
2005-04-07 13:45:56 UTC
Permalink
Post by Hans Galema
Post by Kiwi
I am passing fromURL as shown below
bool WebStuff::AccessInternet(AnsiString sURL, TStringList *fromURL)
std::auto_ptr<TStringList> fromURL(new TStringList);
bool WebStuff::AccessInternet(AnsiString sURL, const
std::auto_ptr<TStringList> &fromURL)
Why would you do that ?
bool WebStuff::AccessInternet(AnsiString sURL, TStringList *fromURL)
would do. Why would AccessInternet() have to know that fromURL
has something to do with an auto_ptr ?
Sometimes people write functions taking an auto_ptr to document two
things:

1) the pointer must point to a heap-allocated object
2) the function takes ownership of that object

Without any words other than auto_ptr, the above two things are
conveyed by the interface.

Sounds great to say so much with so little. However, and there's
always a drawback, this interface can causes some problems. Most
notably, in making the strong exception-safe guarantee such an
interface becomes impossible.

The strong guarantee is that a function either succeeds or fails with
an exception and the state is completely unchanged when the exception
escapes. That is, it's a transactional function with full rollback
semantics. But when you pass an auto_ptr to the function, that
pointer is owned by the function BEFORE the exception is thrown, and
cannot be given back. That means, essentially, that the function is
going to delete the object when an exception is thrown. That means
that the original calling environment CANNOT EVER be restored.

Sometimes this doesn't matter, however. If you create the object for
the sole purpose of giving to that function, then this is the behavior
you want. For example, it's nice under this type of situation:

std::auto_ptr<Something> s( factory->allocate_somthing() );
foo(s);

Above, if foo throws, we still want the object deleted, and by simply
calling foo, the pointer inside s becomes NULL. Thus, if foo doesn't
delete the object, it will be leaked. But this means we cannot have
complete rollback semantics.
--
Chris (TeamB);
Kiwi
2005-04-07 14:02:46 UTC
Permalink
Chris, I am not sure I understand everything you said.

Anyway, in my case:
I am sending fromURL to an Internet Access Function that fills fromURL and
if successful returns true.

If there is an exception it will return false and I will ignore anything in
fromURL and probably try again
to access the internet and fill fromURL.

All my catch functions just record the errors to a file and return false.

I don't think I am changing the state and thought, that in this case, I
could use auto_ptrs without that concern,
and, in this case, auto_ptrs would work okay is this true?

Note, I don't need to use auto_ptrs, my routine works fine without them but
I would just like to understand them
better.

Thanks,
Kiwi
Chris Uzdavinis (TeamB)
2005-04-07 14:23:34 UTC
Permalink
Post by Kiwi
Chris, I am not sure I understand everything you said.
Anyway, in my case: I am sending fromURL to an Internet Access
Function that fills fromURL and if successful returns true.
Fills fromURL? What do you mean by that?
Post by Kiwi
If there is an exception it will return false and I will ignore
anything in fromURL and probably try again to access the internet
and fill fromURL.
The question is, if your function takes an auto_ptr, then the object
your caller passes will no longer exist when that function returns,
whether normally or through an exception. If the TStringList getting
deleted is intentional, then using an auto_ptr should suffice.

All that said, it is relatively rare to see auto_ptrs as function
arguments.
Post by Kiwi
I don't think I am changing the state and thought, that in this
case, I could use auto_ptrs without that concern, and, in this case,
auto_ptrs would work okay is this true?
The stringlist inside the auto_ptr will be deleted, and that's the
state that gets changed.
Post by Kiwi
Note, I don't need to use auto_ptrs, my routine works fine without them but
I would just like to understand them
better.
An auto_ptr owns the pointer it holds, and deletes that pointer when
it goes out of scope. When you copy auto_ptrs, ownership is
transferred from one auto_ptr to another, leaving the original null.

Passing an auto_ptr to a function means that "now the function has
ownership to that pointer, and your caller's auto_ptr does not even
know that address anymore." Further, when the function exits, the
function's auto_ptr is destroyed, which in turn deletes the underlying
object. (Unless your function removes the pointer from the auto_ptr
and saves it somewhere off to the side, but that too is changing the
state of your program, and is not a suggested route to take.)
--
Chris (TeamB);
Hans Galema
2005-04-07 14:35:27 UTC
Permalink
Post by Chris Uzdavinis (TeamB)
Passing an auto_ptr to a function means that "now the function has
ownership to that pointer, and your caller's auto_ptr does not even
know that address anymore." Further, when the function exits, the
function's auto_ptr is destroyed, which in turn deletes the underlying
object. (Unless your function removes the pointer from the auto_ptr
and saves it somewhere off to the side, but that too is changing the
state of your program, and is not a suggested route to take.)
Chris, thanks for explaining about auto_ptr.

I checked "now the function has ownership to that pointer, and your
caller's auto_ptr does not even know that address anymore."

This is true. Amazing world. But not if the call is by reference.

Hans.
Kiwi
2005-04-07 15:11:22 UTC
Permalink
Post by Chris Uzdavinis (TeamB)
Fills fromURL? What do you mean by that?
I just meant

fromURL = HTTP->Get(sURL); // TIdHTTP

then I return the StringList fromURL
Post by Chris Uzdavinis (TeamB)
The question is, if your function takes an auto_ptr, then the object
your caller passes will no longer exist when that function returns,
whether normally or through an exception. If the TStringList getting
deleted is intentional, then using an auto_ptr should suffice.
All that said, it is relatively rare to see auto_ptrs as function
arguments.
Then, I won't use them either.
Post by Chris Uzdavinis (TeamB)
The stringlist inside the auto_ptr will be deleted, and that's the
state that gets changed.
That's okay in my case since if there is an exception I don't want the
Stringlist anyway.
Post by Chris Uzdavinis (TeamB)
An auto_ptr owns the pointer it holds, and deletes that pointer when
it goes out of scope. When you copy auto_ptrs, ownership is
transferred from one auto_ptr to another, leaving the original null.
But, that shouldn't happen if you just pass the reference to the auto_ptr???

Kiwi
Chris Uzdavinis (TeamB)
2005-04-07 15:29:52 UTC
Permalink
Post by Kiwi
Post by Chris Uzdavinis (TeamB)
An auto_ptr owns the pointer it holds, and deletes that pointer when
it goes out of scope. When you copy auto_ptrs, ownership is
transferred from one auto_ptr to another, leaving the original null.
But, that shouldn't happen if you just pass the reference to the auto_ptr???
No, it wouldn't happen. Passing a reference does not create a new
auto_ptr, and so the caller's auto_ptr still maintains control of the
pointer. And the caller's auto_ptr is still in scope when the
function exits.

But what's the point in passing a reference? Why not just pass the
raw pointer itself?
--
Chris (TeamB);
Kiwi
2005-04-07 15:40:26 UTC
Permalink
Post by Chris Uzdavinis (TeamB)
But what's the point in passing a reference? Why not just pass the
raw pointer itself?
Not much, I guess, except you don't have to worry about deleting it.

Anyway, thanks to your discuss I will try to use auto_ptrs more but I will
use
raw pointers as arguments in functions.

Thanks
Kiwi
Hans Galema
2005-04-07 14:53:04 UTC
Permalink
Post by Chris Uzdavinis (TeamB)
That means, essentially, that the function is
going to delete the object when an exception is thrown.
Do you say: it will automatically happen because it is an auto_ptr ?
Or that the function should actifly delete it, (If that is possible for
an auto_ptr). ?
Post by Chris Uzdavinis (TeamB)
Sometimes this doesn't matter, however. If you create the object for
the sole purpose of giving to that function, then this is the behavior
std::auto_ptr<Something> s( factory->allocate_somthing() );
foo(s);
Above, if foo throws, we still want the object deleted, and by simply
calling foo, the pointer inside s becomes NULL. Thus, if foo doesn't
delete the object, it will be leaked.
I did a test where foo caused an AV. Codeguard reported the invalid
memory access but did not report a leak.

So it is auto_ptr and it would leak ?

Hans.
Chris Uzdavinis (TeamB)
2005-04-07 15:10:27 UTC
Permalink
Post by Hans Galema
Post by Chris Uzdavinis (TeamB)
That means, essentially, that the function is
going to delete the object when an exception is thrown.
Do you say: it will automatically happen because it is an auto_ptr ?
Or that the function should actifly delete it, (If that is possible for
an auto_ptr). ?
auto_ptr's will delete the pointer they hold when they are destroyed.
By calling the function, the parameter itself is an auto_ptr that
takes ownership. Unless the function does something special, the
parameter to the function is what actually owns the pointer, and the
objects created for parameters are destroyed when the just before the
function exits.

It'll be deleted automatically, when the arguments are destroyed.
Post by Hans Galema
I did a test where foo caused an AV. Codeguard reported the invalid
memory access but did not report a leak.
So it is auto_ptr and it would leak ?
Could you show the entire code you tested, and restate your question?
I don't quite understand what you're asking.

Also, when an auto_ptr holds a pointer, it will not leak. Whenever
the scope of the auto_ptr is exited, the pointer will be deleted.
--
Chris (TeamB);
Hans Galema
2005-04-07 15:20:45 UTC
Permalink
Post by Chris Uzdavinis (TeamB)
Could you show the entire code you tested, and restate your question?
You spoke of a leak in case foo() threw.

I did the following test:

#include <memory>
bool TForm1::AccessStringList( std::auto_ptr<TStringList>StringList )
{
char *ptr = 0;

*ptr = 0; // causes an AV
// rest of code not executed

StringList->Add ( "Line Three");

ShowMessage ( StringList->Text );

return true;
}

void __fastcall TForm1::Button1Click(TObject *Sender)
{
std::auto_ptr<TStringList>StringList(new TStringList);

StringList->Add ( "First Line");
StringList->Add ( "Second Line");

AccessStringList( StringList );
}

Codeguard reports the AV but does not report a memoryleak.
This is what I expect for an auto_ptr.

But you were talking of a leak.

No leak found.

Hans.
Chris Uzdavinis (TeamB)
2005-04-07 15:59:40 UTC
Permalink
Post by Hans Galema
Post by Chris Uzdavinis (TeamB)
Could you show the entire code you tested, and restate your question?
You spoke of a leak in case foo() threw.
Oh, I see what you mean. I suppose a clairification is in order.

My main point was "if foo returned and the object was not deleted, it
would be leaked" since the caller loses its reference to the pointer.

More detailed: if you give ownership of your heap-allocated pointer to
another function, then it's that function's responsibility to delete
it. It may use an auto_ptr to accomplish this (and passing auto_ptr
as an argument could satisfy this requirement), or it could explicitly
delete the pointer if no auto_ptr were involved, or alternately, could
give the pointer to yet another function that took responsibility to
delete it. As long as it is deleted, it doesn't matter who did it.

So what I meant by "if foo doesn't delete the object, it will be
leaked." wasn't that foo had to explicitly delete the object, but by
the time foo returns, the object should be deleted somehow.
Post by Hans Galema
#include <memory>
bool TForm1::AccessStringList( std::auto_ptr<TStringList>StringList )
{
char *ptr = 0;
*ptr = 0; // causes an AV
// rest of code not executed
An access violation shouldn't be considered an exception. This is a
bug that has undefined behavior. For an real exception, you need to
have a "throw" expression.

...
Post by Hans Galema
But you were talking of a leak.
No leak found.
Yes, it was hypothetical. If the pointer wasn't deleted inside the
function, it would have been leaked. But the pointer was deleted,
hence no leak. :)
--
Chris (TeamB);
Hans Galema
2005-04-07 16:25:20 UTC
Permalink
Post by Chris Uzdavinis (TeamB)
Oh, I see what you mean. I suppose a clairification is in order.
Ok. I understand. Thanks for the clarification.

Hans.
Remy Lebeau (TeamB)
2005-04-07 18:03:46 UTC
Permalink
Post by Kiwi
Remy introduced me to auto_ptrs and I was wondering how
to pass an auto_ptr as an argument in a function
Do not pass the auto_ptr itself. The auto_ptr class has a get() method so
that you can retreive the pointer that it is holding on to, ie:

bool WebStuff::AccessInternet(const AnsiString &sURL, TStringList
*fromURL);

std::auto_ptr<TStringList> fromURL(new TStringList);
AccessInternet("some URL", fromURL.get());


Gambit
Duane Hebert
2005-04-07 19:09:58 UTC
Permalink
Post by Remy Lebeau (TeamB)
Post by Kiwi
Remy introduced me to auto_ptrs and I was wondering how
to pass an auto_ptr as an argument in a function
Do not pass the auto_ptr itself. The auto_ptr class has a get() method so
bool WebStuff::AccessInternet(const AnsiString &sURL, TStringList
*fromURL);
std::auto_ptr<TStringList> fromURL(new TStringList);
AccessInternet("some URL", fromURL.get());
Or use one of the boost pointers like boost::shared_ptr.

Continue reading on narkive:
Loading...