By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,421 Members | 1,127 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,421 IT Pros & Developers. It's quick & easy.

Is this valid and moral C++?

P: n/a
Suppose that we have a function

f(Object*& obj)

and have declared a global std::vector<Object*vec;

Is it valid to do

void g() {
vec.push_back(new Object);
f(vec.back());
}

ie does f() internally actually have read/write access to the Object
allocated in g() on the heap? If not, what would be the trick to achieve
this? Thanks,

filimon
Mar 18 '07 #1
Share this Question
Share on Google+
30 Replies


P: n/a
Filimon Roukoutakis wrote:
Suppose that we have a function

f(Object*& obj)

and have declared a global std::vector<Object*vec;

Is it valid to do

void g() {
vec.push_back(new Object);
f(vec.back());
}

ie does f() internally actually have read/write access to the Object
allocated in g() on the heap? If not, what would be the trick to achieve
this? Thanks,
Yes, it is valid.

Objects allocated by new are available to any function before delete is
called on it.
Mar 18 '07 #2

P: n/a
On Sun, 18 Mar 2007 21:09:22 +0100 in comp.lang.c++, Filimon Roukoutakis
<fi*****@phys.uoa.grwrote,
>Suppose that we have a function

f(Object*& obj)

and have declared a global std::vector<Object*vec;

Is it valid to do

void g() {
vec.push_back(new Object);
f(vec.back());
}
No. The function should receive the pointer argument by value. i.e.
f(Object* obj)

It is invalid to try to pass a modifiable reference to the result of
..back() , and while a const reference would work it has no particular
advantage.

Secondly, your global vector of Object* will NOT delete the objects
pointed to when it's destructor runs at the end of the program. There's
no big deal about reclaiming the memory at that point, but if Object's
destructor does anything else important you've got a problem.
>ie does f() internally actually have read/write access to the Object
allocated in g() on the heap?
Yes. In fact that is the only way of accessing the object that you have
left yourself at this point, which is fine.

Mar 18 '07 #3

P: n/a
David Harmon wrote:
On Sun, 18 Mar 2007 21:09:22 +0100 in comp.lang.c++, Filimon Roukoutakis
<fi*****@phys.uoa.grwrote,
>Suppose that we have a function

f(Object*& obj)

and have declared a global std::vector<Object*vec;

Is it valid to do

void g() {
vec.push_back(new Object);
f(vec.back());
}

No. The function should receive the pointer argument by value. i.e.
f(Object* obj)

It is invalid to try to pass a modifiable reference to the result of
.back() , and while a const reference would work it has no particular
advantage.

Why is it "invalid" ?
Mar 18 '07 #4

P: n/a
David Harmon wrote:
On Sun, 18 Mar 2007 21:09:22 +0100 in comp.lang.c++, Filimon Roukoutakis
<fi*****@phys.uoa.grwrote,
>Suppose that we have a function

f(Object*& obj)

and have declared a global std::vector<Object*vec;

Is it valid to do

void g() {
vec.push_back(new Object);
f(vec.back());
}

No. The function should receive the pointer argument by value. i.e.
f(Object* obj)

It is invalid to try to pass a modifiable reference to the result of
.back() , and while a const reference would work it has no particular
advantage.
I do want to pass a reference to the pointer so the pointer is
modifiable, or more precicely I want to use this pointer in another
context in the program while it is by itself updated by f. Could you
comment on the invalidity of modifiable reference?
>
Secondly, your global vector of Object* will NOT delete the objects
pointed to when it's destructor runs at the end of the program. There's
no big deal about reclaiming the memory at that point, but if Object's
destructor does anything else important you've got a problem.
>ie does f() internally actually have read/write access to the Object
allocated in g() on the heap?

Yes. In fact that is the only way of accessing the object that you have
left yourself at this point, which is fine.
ok for the above I knew, it was just a minimal example.

filimon
Mar 18 '07 #5

P: n/a
David Harmon wrote:
On Sun, 18 Mar 2007 21:09:22 +0100 in comp.lang.c++, Filimon Roukoutakis
<fi*****@phys.uoa.grwrote,
>>Suppose that we have a function

f(Object*& obj)

and have declared a global std::vector<Object*vec;

Is it valid to do

void g() {
vec.push_back(new Object);
f(vec.back());
}

No. The function should receive the pointer argument by value. i.e.
f(Object* obj)
Why?
It is invalid to try to pass a modifiable reference to the result of
.back() , and while a const reference would work it has no particular
advantage.
The call f(vec.back()) does not pass anything "to the result of .back()".
What it does is: it initializes the Object*& parameter of f() with the
result of vec.back(), which so happens to be a reference (non-const in case
the non-const version of back() is called). There is nothing invalid about
it, as far as I can see.

E.g., f() could be:

f ( Object* & p_ref ) {
Object * dummy = new Object ();
std::swap( p_ref, dummy );
delete dummy;
}

Then f(vec.back()) would replace the last pointer with a new pointer whose
pointee has been default constructed.

Secondly, your global vector of Object* will NOT delete the objects
pointed to when it's destructor runs at the end of the program. There's
no big deal about reclaiming the memory at that point, but if Object's
destructor does anything else important you've got a problem.
Right: the vector will not do that by itself. So, the OP will have to take
care of deleting the pointers by himself.
[snip]

Mar 18 '07 #6

P: n/a
On Sun, 18 Mar 2007 22:37:29 +0100 in comp.lang.c++, Filimon Roukoutakis
<fi*****@phys.uoa.grwrote,
>I do want to pass a reference to the pointer so the pointer is
modifiable, or more precicely I want to use this pointer in another
context in the program while it is by itself updated by f. Could you
comment on the invalidity of modifiable reference?
What does it mean when your code attempts to modify via the reference,
giving in effect:
vec.back() = (some expression);

As I wrote to Gianni, It is forbidden by the standard to bind a
non-const reference to a temporary. This is one case where that rule
probably even makes sense. If you could actually change the value of
vec.back() without resizing the vector, it would break the vector. If
you think you can resize the vector by, for instance, incrementing
vec.back(), it doesn't work that way.

Mar 18 '07 #7

P: n/a
On Mon, 19 Mar 2007 08:30:34 +1100 in comp.lang.c++, Gianni Mariani
<gi*******@mariani.wswrote,
>It is invalid to try to pass a modifiable reference to the result of
.back() , and while a const reference would work it has no particular
advantage.


Why is it "invalid" ?
It is forbidden by the standard to bind a non-const reference to a
temporary. This is one case where that rule probably even makes sense.
If you could actually change the value of vec.back() without resizing
the vector, it would break the vector. If you think you can resize the
vector by, for instance, incrementing vec.back(), it doesn't work that
way.

Mar 18 '07 #8

P: n/a
On Sun, 18 Mar 2007 18:13:46 -0400 in comp.lang.c++, Kai-Uwe Bux
<jk********@gmx.netwrote,
>The call f(vec.back()) does not pass anything "to the result of .back()".
What it does is: it initializes the Object*& parameter of f() with the
result of vec.back(), which so happens to be a reference (non-const in case
the non-const version of back() is called). There is nothing invalid about
it, as far as I can see.
Doh! I was confusing the element access front() and back() with the
iterator functions begin() etc. Disregard all.
Mar 18 '07 #9

P: n/a
On Mon, 19 Mar 2007 08:30:34 +1100 in comp.lang.c++, Gianni Mariani
<gi*******@mariani.wswrote,
>It is invalid to try to pass a modifiable reference to the result of
.back() , and while a const reference would work it has no particular
advantage.


Why is it "invalid" ?

Doh! I was confusing the element access front() and back() with the
iterator functions begin() etc. Disregard all.
Mar 18 '07 #10

P: n/a
On Sun, 18 Mar 2007 22:37:29 +0100 in comp.lang.c++, Filimon Roukoutakis
<fi*****@phys.uoa.grwrote,
>context in the program while it is by itself updated by f. Could you
comment on the invalidity of modifiable reference?
Doh! I was confusing the element access front() and back() with the
iterator functions begin() etc. Disregard all.

Mar 18 '07 #11

P: n/a
"Filimon Roukoutakis" <fi*****@phys.uoa.grwrote in message
news:et**********@cernne03.cern.ch...
Suppose that we have a function

f(Object*& obj)

and have declared a global std::vector<Object*vec;

Is it valid to do

void g() {
vec.push_back(new Object);
f(vec.back());
}

ie does f() internally actually have read/write access to the Object
allocated in g() on the heap? If not, what would be the trick to achieve
this? Thanks,
By your replies to the other posts, I take it you meant

void g() {
vec push_back( new Object );
f( vec[size() - 1] );
}

f( *(vec.end() - 1) );
may also work.

Your question seems to be, g made a new object, can f access that object?
The answer is yes. It would be the same if you did something like:

Object* MyObject = NULL;

f( Object*& obj )
{
// ...
}

Object* g
{
return new Object;
}

int main()
{
MyObject = g();
f( MyObject );
delete( MyObject );
}

You just happen to be storing it in a vector instead of (in thsi case) a
global variable. Once an object is allocated using new all you need is the
pointer to that memory to access the instance, until delete is called on it.
However you happen to get that pointer (global, from a vecotr, a paramter,
whatever).

Incidently, now a days "heap" is commonly called the "free store". I'm not
sure what the standard calls it.

Just make sure you delete the pointer when done.
Mar 18 '07 #12

P: n/a
Jim Langston wrote:
"Filimon Roukoutakis" <fi*****@phys.uoa.grwrote in message
news:et**********@cernne03.cern.ch...
>Suppose that we have a function

f(Object*& obj)

and have declared a global std::vector<Object*vec;

Is it valid to do

void g() {
vec.push_back(new Object);
f(vec.back());
}

ie does f() internally actually have read/write access to the Object
allocated in g() on the heap? If not, what would be the trick to achieve
this? Thanks,

By your replies to the other posts, I take it you meant

void g() {
vec push_back( new Object );
f( vec[size() - 1] );
}

f( *(vec.end() - 1) );
may also work.

Your question seems to be, g made a new object, can f access that object?
The answer is yes. It would be the same if you did something like:

Object* MyObject = NULL;

f( Object*& obj )
{
// ...
}

Object* g
{
return new Object;
}

int main()
{
MyObject = g();
f( MyObject );
delete( MyObject );
}

You just happen to be storing it in a vector instead of (in thsi case) a
global variable. Once an object is allocated using new all you need is the
pointer to that memory to access the instance, until delete is called on it.
However you happen to get that pointer (global, from a vecotr, a paramter,
whatever).

Incidently, now a days "heap" is commonly called the "free store". I'm not
sure what the standard calls it.

Just make sure you delete the pointer when done.

My problem is that when I try to delete the pointer inside f I get a
segmentation violation, so I figured that maybe new Object inside g is
stored as a const reference in the vector which cannot be modified
somehow and this produces the problem.
Mar 19 '07 #13

P: n/a
On Mon, 19 Mar 2007 10:28:48 +0100 in comp.lang.c++, Filimon Roukoutakis
<fi*****@phys.uoa.grwrote,
>
My problem is that when I try to delete the pointer inside f I get a
segmentation violation, so I figured that maybe new Object inside g is
stored as a const reference in the vector which cannot be modified
somehow and this produces the problem.
No. The contents of the vector, in this case the pointers, are fully
modifiable just as you thought. Even if that were not the case, const
pointers can be deleted as long as they came from 'new' to begin with.
I apologize for muddying the waters.

seg violation on deleting usually means either you are trying to delete
the same object twice, or some pointer that was never new'ed, or that
some random memory write elsewhere in the program has corrupted the
heap. Or something along those lines. Can be tricky to track down.

Mar 20 '07 #14

P: n/a
"Filimon Roukoutakis" <fi*****@phys.uoa.grwrote in message
news:et**********@cernne03.cern.ch...
: Suppose that we have a function
:
: f(Object*& obj)
:
: and have declared a global std::vector<Object*vec;
:
: Is it valid to do
:
: void g() {
: vec.push_back(new Object);
: f(vec.back());
: }
:
: ie does f() internally actually have read/write access to the Object
: allocated in g() on the heap? If not, what would be the trick to
achieve
: this? Thanks,

That part is ok. The only problem I see in the above code is
something that hasn't been mentioned yet:
vec.push_back(new Object);
This is not exception-safe: if push_back fails (because it
is unable to allocate a larger block of memory), the newly
allocated object will be leaked.

But this of course will be unrelated to the problem
you described later.
For that, be careful that you do not modify the vector
(e.g. by adding another element) as long as you are
using the reference returned by back().

hth -Ivan

--
http://ivan.vecerina.com/contact/?subject=NG_POST <- email contact form

Mar 20 '07 #15

P: n/a
On Tue, 20 Mar 2007 07:27:17 +0100, "Ivan Vecerina" wrote:
>The only problem I see in the above code is
something that hasn't been mentioned yet:
vec.push_back(new Object);
This is not exception-safe: if push_back fails (because it
is unable to allocate a larger block of memory), the newly
allocated object will be leaked.
Out-of-memory in C++ is usually handled by the new_handler, not with
exception handling. If one really needs to handle OOM with exception
handling vector::reserve() may be called in advance.

Best regards,
Roland Pibinger
Mar 20 '07 #16

P: n/a
"Roland Pibinger" <rp*****@yahoo.comwrote in message
news:45**************@news.utanet.at...
: On Tue, 20 Mar 2007 07:27:17 +0100, "Ivan Vecerina" wrote:
: >The only problem I see in the above code is
: >something that hasn't been mentioned yet:
: vec.push_back(new Object);
: >This is not exception-safe: if push_back fails (because it
: >is unable to allocate a larger block of memory), the newly
: >allocated object will be leaked.
:
: Out-of-memory in C++ is usually handled by the new_handler, not with
: exception handling.

What is your definition of "usually" ???
http://www.google.com/codesearch?q=set_new_handler
This gives 2-3'000 hits, many of them being declarations
in library headers. Not quite was I would call "usual".
Plus new_handler is required to either throw an exception,
or terminate the program. Does it really help here ?

: If one really needs to handle OOM with exception
: handling vector::reserve() may be called in advance.

Yes, this is one of several ways to address the problem.
All I am saying is that this issue is worth attention.

Regards,
Ivan

--
http://ivan.vecerina.com/contact/?subject=NG_POST <- email contact form
Brainbench MVP for C++ <http://www.brainbench.com

Mar 22 '07 #17

P: n/a
Filimon Roukoutakis wrote:
Suppose that we have a function

f(Object*& obj)

and have declared a global std::vector<Object*vec;

Is it valid to do

void g() {
vec.push_back(new Object);
f(vec.back());
}

ie does f() internally actually have read/write access to the Object
allocated in g() on the heap? If not, what would be the trick to achieve
this? Thanks,

filimon
Problem solved. The problem was that the above code produced a
segmentation violation in another part of the program. The fix was to
replace std::vector<Object*with std::vector<Object**and
vec.push_back(new Object*). Probably this was not obvious in the context
of the code snippet that was presented here. Thanks for the answers.

filimon
Mar 23 '07 #18

P: n/a
"Filimon Roukoutakis" <fi*****@phys.uoa.grwrote in message
news:eu**********@cernne03.cern.ch...
Filimon Roukoutakis wrote:
>Suppose that we have a function

f(Object*& obj)

and have declared a global std::vector<Object*vec;

Is it valid to do

void g() {
vec.push_back(new Object);
f(vec.back());
}

ie does f() internally actually have read/write access to the Object
allocated in g() on the heap? If not, what would be the trick to achieve
this? Thanks,

filimon

Problem solved. The problem was that the above code produced a
segmentation violation in another part of the program. The fix was to
replace std::vector<Object*with std::vector<Object**and
vec.push_back(new Object*). Probably this was not obvious in the context
of the code snippet that was presented here. Thanks for the answers.
std::vector<someclass*is usually bad design unless you are working with
polymorphism. Even then some would say use a smart pointer (although I use
naked pointers myself).

std::vector<someclass**I could only think is bad design. You may want to
relook at what you are doing and see if this is absolutly necessary, it
sounds like a maintainance nightmare.
Mar 24 '07 #19

P: n/a
Filimon Roukoutakis wrote:
:: Filimon Roukoutakis wrote:
::: Suppose that we have a function
:::
::: f(Object*& obj)
:::
::: and have declared a global std::vector<Object*vec;
:::
::: Is it valid to do
:::
::: void g() {
::: vec.push_back(new Object);
::: f(vec.back());
::: }
:::
::: ie does f() internally actually have read/write access to the Object
::: allocated in g() on the heap? If not, what would be the trick to
::: achieve this? Thanks,
:::
::: filimon
::
:: Problem solved. The problem was that the above code produced a
:: segmentation violation in another part of the program. The fix was to
:: replace std::vector<Object*with std::vector<Object**and
:: vec.push_back(new Object*).

Agreeing with Jim Langston's post, I can only say that dynamically
allocating a single pointer is EXTREMELY unusual.

In my opinion, it is HIGHLY LIKELY that you have not actually solved the
problem, but only happen to hide it.
Bo Persson
Mar 24 '07 #20

P: n/a

Ivan Vecerina wrote:
Yes, this is one of several ways to address the problem.
All I am saying is that this issue is worth attention.
Yes, I cannot understand Roland's point too. Obviously reserve might
solve the problem. I think it could cause unnecessary memory
allocation though. I would prefer:

std::auto_ptr<Objectinstance( new Object );
myVector.push_back( instance.get() ); //X
instance.release(); //No X

Werner

Mar 24 '07 #21

P: n/a
werasm wrote:
>
Ivan Vecerina wrote:
>Yes, this is one of several ways to address the problem.
All I am saying is that this issue is worth attention.

Yes, I cannot understand Roland's point too. Obviously reserve might
solve the problem. I think it could cause unnecessary memory
allocation though. I would prefer:

std::auto_ptr<Objectinstance( new Object );
myVector.push_back( instance.get() ); //X
instance.release(); //No X
Alternatively,

myVector.push_back( 0 );
myVector.back() = new Object;

looks exception safe, too.
Best

Kai-Uwe Bux
Mar 24 '07 #22

P: n/a
On 24 Mar 2007 08:04:48 -0700, "werasm" wrote:
>Yes, this is one of several ways to address the problem.
All I am saying is that this issue is worth attention.
Yes, I cannot understand Roland's point too. Obviously reserve might
solve the problem. I think it could cause unnecessary memory
allocation though.
OOM can be handled by a global new_handler if the operating system
supports it. Linux e.g. uses 'optimistic memory allocation' so
checking for OOM exceptions is not useful there. See also Moral #2
here: http://www.gotw.ca/publications/mill16.htm
>I would prefer:

std::auto_ptr<Objectinstance( new Object );
myVector.push_back( instance.get() ); //X
instance.release(); //No X
This is impractical for any real-world program. In general you need
not check within your program for OOM, stack overflow, int overflow,
etc.. You can reasonably assume that you are in 'secure territory'.

Best wishes,
Roland Pibinger


Mar 24 '07 #23

P: n/a
"Roland Pibinger" <rp*****@yahoo.comwrote in message
news:46**************@news.utanet.at...
: On 24 Mar 2007 08:04:48 -0700, "werasm" wrote:
: >Yes, this is one of several ways to address the problem.
: >All I am saying is that this issue is worth attention.
: >>
: >Yes, I cannot understand Roland's point too. Obviously reserve might
: >solve the problem. I think it could cause unnecessary memory
: >allocation though.
:
: OOM can be handled by a global new_handler if the operating system
: supports it. Linux e.g. uses 'optimistic memory allocation' so
: checking for OOM exceptions is not useful there. See also Moral #2
: here: http://www.gotw.ca/publications/mill16.htm

I rarely check for new/memory allocations in my code. I only do my
best to write code that is exception-safe. New-ing an object can
fail in any case because of a constructor failure.
Given, push_back of a pointer is unlikely to fail, yet formally
it is a container operation that is allowed to fail and throw
an exception. So I'll write my code "to the spec".

: >I would prefer:
: >
: >std::auto_ptr<Objectinstance( new Object );
: >myVector.push_back( instance.get() ); //X
: >instance.release(); //No X
:
: This is impractical for any real-world program.

Indeed. The real issue is that it is illegal to create a
container of auto_ptr. vector<T*is brittle by nature.

When I have a container of polymorphic objects, I find
that the overhead of vector< shared_ptr<T is acceptable.
When not using polymorphic objects, I do not use containers
of pointers, but a container of <T- with possibly some
accessory "index" containers storing pointers that refer
into an "allocation" container (a list or deque).

In C++0x, with the introduction of R-value references, I expect
that an equivalent of vector< auto_ptr<T will become available
in the standard library.

: In general you need
: not check within your program for OOM, stack overflow, int overflow,
: etc.. You can reasonably assume that you are in 'secure territory'

I write software for medical devices.

You think that one can just assume that int overflows never happen?

void on_decrement_radiation_power()
{
--ray_power; // safe? what if unsigned ray_power was zero?
}

Depending on the type of device your code runs on, you will also
ensure that stack overflows can't be triggered by excessive
recursion, or ensure graceful failure if sufficient memory
isn't available for new incoming data.
Cheers -Ivan
--
http://ivan.vecerina.com/contact/?subject=NG_POST <- email contact form

Mar 25 '07 #24

P: n/a

Ivan Vecerina wrote:
: >I would prefer:
: >
: >std::auto_ptr<Objectinstance( new Object );
: >myVector.push_back( instance.get() ); //X
: >instance.release(); //No X
:
Indeed. The real issue is that it is illegal to create a
container of auto_ptr. vector<T*is brittle by nature.
Yes, but you of course realise that the container was not a container
of auto_ptr's. Notice the <get()in the call to push_back. The
container only contained normal pointers, hence the call to release
afterwards.

That said, I have read the article Roland mentioned. For me it is
actually concerning that the possibility exists that a call to
something like buffer_[x] = 'y' might fail with a much worse exception
than bad_alloc (like an access violation). Even when one does get to
the situation where memory becomes a problem (and this is certainly a
possibility, especially when writing application where resources are
constraining - embedded linux), one would like to have the means of
taking action.

For instance, take your medical applications for example:

In the event of memory failure, one would possible want to disable a
less critical portion of the program, freeing its memory and allowing
for a more critical portion to try again - especially when a life
depends on the execution of a more critical part.

I suppose for these kinds of programs one will have to revert to pre-
allocated memory period (possible overloading new/deletes to only us
this). How do you even know whether the pre-allocated memory was
really allocated?

Although memory failure is very rare, if it is a possibility at all,
one would like it to fail deterministically.

Regards,

Werner

Mar 25 '07 #25

P: n/a
On Sun, 25 Mar 2007 10:48:07 +0200, "Ivan Vecerina" wrote:
>I rarely check for new/memory allocations in my code. I only do my
best to write code that is exception-safe. New-ing an object can
fail in any case because of a constructor failure.
Yes, constructor failure is something you expect. It's entirely
different from OOM, stack overflow, ...
>Given, push_back of a pointer is unlikely to fail, yet formally
it is a container operation that is allowed to fail and throw
an exception. So I'll write my code "to the spec".
Allowed, but not required. So maybe the spec is defective?
>The real issue is that it is illegal to create a
container of auto_ptr. vector<T*is brittle by nature.
When I have a container of polymorphic objects, I find
that the overhead of vector< shared_ptr<T is acceptable.
I don't think that 'smart pointes' solve any problem (BTW, a container
for auto_ptrs is not difficult but why should one use it? See:
http://www.relisoft.com/resource/auto_vector.html).
>Depending on the type of device your code runs on, you will also
ensure that stack overflows can't be triggered by excessive
recursion, or ensure graceful failure if sufficient memory
isn't available for new incoming data.
IMO, the question is which resources you can rely on withing your
program and which not. Checking for stack overflow, OOM, ... would
severely impair the creation of reusable components. You must rely on
some solid ground for your programming.

Best wishes,
Roland Pibinger
Mar 25 '07 #26

P: n/a
"Roland Pibinger" <rp*****@yahoo.comwrote in message
news:46*************@news.utanet.at...
: On Sun, 25 Mar 2007 10:48:07 +0200, "Ivan Vecerina" wrote:
: >I rarely check for new/memory allocations in my code. I only do my
: >best to write code that is exception-safe. New-ing an object can
: >fail in any case because of a constructor failure.
:
: Yes, constructor failure is something you expect. It's entirely
: different from OOM, stack overflow, ...

As I previously pointed out, what you expect is dependent on
the platform and application that you are working on.

: >Given, push_back of a pointer is unlikely to fail, yet formally
: >it is a container operation that is allowed to fail and throw
: >an exception. So I'll write my code "to the spec".
:
: Allowed, but not required. So maybe the spec is defective?

You mean, maybe the experience of the designers of the C++
language and libraries pales in comparison to yours?
You mean, it should not be possible to write an allocator
that can fail to allocate memory on a platform with limited
resources, and throw an exception to allow graceful recovery?

: >The real issue is that it is illegal to create a
: >container of auto_ptr. vector<T*is brittle by nature.
: >When I have a container of polymorphic objects, I find
: >that the overhead of vector< shared_ptr<T is acceptable.
:
: I don't think that 'smart pointes' solve any problem

Smart pointers (seek to) address the problem of memory leaks.
In your opinion, so many people have been working on smart
pointers for no reason ?

: (BTW, a container
: for auto_ptrs is not difficult but why should one use it?
: See: http://www.relisoft.com/resource/auto_vector.html).

The difficulty of implementing a solution is proportional
to the breadth of its applicability.
Have you considered, for example, that:
- you'd have to rewrite a whole separate container
to have an auto_list
- it is unsafe to use auto_vector::iterator with
many standard algorithms, such as std::unique

I would suggest reading this introduction to R-value references
http://www.open-std.org/jtc1/sc22/wg...2002/n1377.htm
[ here's a convenient index into more info about R-value
references and other C++ features that are in development:
http://www.open-std.org/jtc1/sc22/wg...007/n2169.html ]

: >Depending on the type of device your code runs on, you will also
: >ensure that stack overflows can't be triggered by excessive
: >recursion, or ensure graceful failure if sufficient memory
: >isn't available for new incoming data.
:
: IMO, the question is which resources you can rely on withing your
: program and which not.
This is simple: what can be relied on or not, for portable C++ code,
is defined in the C++ standard. And according to this specification,
vector::push_back is allowed to throw an exception.

: Checking for stack overflow, OOM, ... would
: severely impair the creation of reusable components.

I have never suggested checking for stack overflow. But if I write
a recursive algorithms I will make sure, for example, that its
worst case recursion depth is logarithmic to the size of its input.
I do not specifically check for out-of-memory exceptions, but I use
RAII-related idioms to write code that is (hopefully) exception-safe
and immune to resource leaks.

: You must rely on some solid ground for your programming.

Isn't this exactly what I am doing by not making
platform-specific assumptions?
Take care -Ivan
--
http://ivan.vecerina.com/contact/?subject=NG_POST <- email contact form

Mar 26 '07 #27

P: n/a
Hi, Werner,
"werasm" <we****@gmail.comwrote in message
news:11**********************@d57g2000hsg.googlegr oups.com...
:
: Ivan Vecerina wrote:
:
: : >I would prefer:
: : >
: : >std::auto_ptr<Objectinstance( new Object );
: : >myVector.push_back( instance.get() ); //X
: : >instance.release(); //No X
: :
: Indeed. The real issue is that it is illegal to create a
: container of auto_ptr. vector<T*is brittle by nature.
:
: Yes, but you of course realise that the container was not a container
: of auto_ptr's. Notice the <get()in the call to push_back. The
: container only contained normal pointers, hence the call to release
: afterwards.

My comment was not about the correctness of the solution
you posted (no question about this). I was only regretting
that it required 3 lines of code instead of one.

: That said, I have read the article Roland mentioned. For me it is
: actually concerning that the possibility exists that a call to
: something like buffer_[x] = 'y' might fail with a much worse exception
: than bad_alloc (like an access violation). Even when one does get to
: the situation where memory becomes a problem (and this is certainly a
: possibility, especially when writing application where resources are
: constraining - embedded linux), one would like to have the means of
: taking action.

This implementation approach ("lazy commit") might be a reasonable
choice for destop systems - assuming that the user is alerted when
swap memory nears exhaustion, and that the user will first notice
system thrashing and look into releasing memory.
I am not a linux expert, but on many platforms it is possible to
specify the maximum memory that can be allocated to a process,
and I wouldn't be surprised if this were the case in Linux as well.
Critical applications and servers may use their own allocators,
and impose hard limits on their total resource allocations
(or use other hard limits, such as the maximum number of sessions
that a server may open simultaneously).
Tuning these hard limits is part of the job of a competent
server system administrator...

: For instance, take your medical applications for example:
:
: In the event of memory failure, one would possible want to disable a
: less critical portion of the program, freeing its memory and allowing
: for a more critical portion to try again - especially when a life
: depends on the execution of a more critical part.

Small embedded critical systems simply avoid making any memory
allocations at all.
As aplications and devices become more complex, the emphasis
is not as much on avoiding any failure (difficult to prove) as
on making sure that failure is handled gracefully.
On an X-ray machine, an external watchdog will immediately stop
all irradiation if the software stops responding, or if a certain
output threshold is reached). In your car a shut-down of the
ABS electronics will not prevent (mechanically-transmitted)
breaking force from functioning (unless you have one of these
specific models that attempted break-by-wire).

: Although memory failure is very rare, if it is a possibility at all,
: one would like it to fail deterministically.
Yes.

Kind regards,
Ivan
--
http://ivan.vecerina.com/contact/?subject=NG_POST <- email contact form

Mar 26 '07 #28

P: n/a
Jim Langston wrote:
"Filimon Roukoutakis" <fi*****@phys.uoa.grwrote in message
news:eu**********@cernne03.cern.ch...
>Filimon Roukoutakis wrote:
>>Suppose that we have a function

f(Object*& obj)

and have declared a global std::vector<Object*vec;

Is it valid to do

void g() {
vec.push_back(new Object);
f(vec.back());
}

ie does f() internally actually have read/write access to the Object
allocated in g() on the heap? If not, what would be the trick to achieve
this? Thanks,

filimon
Problem solved. The problem was that the above code produced a
segmentation violation in another part of the program. The fix was to
replace std::vector<Object*with std::vector<Object**and
vec.push_back(new Object*). Probably this was not obvious in the context
of the code snippet that was presented here. Thanks for the answers.

std::vector<someclass*is usually bad design unless you are working with
polymorphism. Even then some would say use a smart pointer (although I use
naked pointers myself).
I am working with polymorphism. At some point I was reading strong
statements about not using std::smart_ptr with std::containers. Did I
misunderstand?
>
std::vector<someclass**I could only think is bad design. You may want to
relook at what you are doing and see if this is absolutly necessary, it
sounds like a maintainance nightmare.

Mar 26 '07 #29

P: n/a
"Filimon Roukoutakis" <fi*****@phys.uoa.grwrote in message
news:eu**********@cernne03.cern.ch...
Jim Langston wrote:
>"Filimon Roukoutakis" <fi*****@phys.uoa.grwrote in message
news:eu**********@cernne03.cern.ch...
>>Filimon Roukoutakis wrote:
Suppose that we have a function

f(Object*& obj)

and have declared a global std::vector<Object*vec;

Is it valid to do

void g() {
vec.push_back(new Object);
f(vec.back());
}

ie does f() internally actually have read/write access to the Object
allocated in g() on the heap? If not, what would be the trick to
achieve this? Thanks,

filimon
Problem solved. The problem was that the above code produced a
segmentation violation in another part of the program. The fix was to
replace std::vector<Object*with std::vector<Object**and
vec.push_back(new Object*). Probably this was not obvious in the context
of the code snippet that was presented here. Thanks for the answers.

std::vector<someclass*is usually bad design unless you are working with
polymorphism. Even then some would say use a smart pointer (although I
use naked pointers myself).

I am working with polymorphism. At some point I was reading strong
statements about not using std::smart_ptr with std::containers. Did I
misunderstand?
Probably not. There are a few people who don't like smart pointers for
various reasons.

The question becomes, then, why do you need a someclass** instead of a
class*? Unless you are changing where the pointer is pointing somewhere, in
which case wouldn't it just be better to overwrite the value?
Mar 26 '07 #30

P: n/a
In message <eu**********@cernne03.cern.ch>, Filimon Roukoutakis
<fi*****@phys.uoa.grwrites
>Jim Langston wrote:
[...]
> std::vector<someclass*is usually bad design unless you are working
with polymorphism. Even then some would say use a smart pointer
(although I use naked pointers myself).

I am working with polymorphism. At some point I was reading strong
statements about not using std::smart_ptr with std::containers. Did I
misunderstand?
There's no such animal as std::smart_ptr, so the question is what kind
of pointer they really meant. Probably they meant that you can't have
std::containers of std::auto_ptr, because it doesn't model normal copy
semantics.

--
Richard Herring
Apr 3 '07 #31

This discussion thread is closed

Replies have been disabled for this discussion.