Topic: is C++ implementation allowed to store object in non-continuous area of memory ?
Author: hickin@cam.org ("John D. Hickin")
Date: Tue, 22 Jul 2003 00:23:40 +0000 (UTC) Raw View
"Francis Glassborow" <francis@robinton.demon.co.uk> wrote in message
news:vfKOz8AFo7D$EwoU@robinton.demon.co.uk...
> In article <vgtp84dh21hd21@corp.supernews.com>, Victor Bazarov
>
> I am sorry if this is confused. But it is quite clear that even if some
> perverted reading of the standard allows otherwise the only logical
> mechanism is for all complete objects with the same dynamic type to have
> the same layout. I have to say complete type because virtual bases and
> MI introduce the necessity that some subobjects will be disjoint.
> However I do not believe that it is allowed to try to destroy a base
> subobject other than as part of the destruction of the complete object.
>
How about a compiler that aims to minimize re-compilation? It is conceivable
that all objects could be treated as if they were PIMPLs, i.e.,
class X {
...
};
could be treated, under the hood, as if it were declared like this:
class X {
class XImpl { ... } *pImpl;
// other stuff potentially needed here (1)
};
and so on, recursively. When an object is constructed, it could then be
scattered in memory; only the _top_ part could be placed by the user, and
the other memory chunks could be allocated as needed (under the hood, out of
reach of user-written code). This type of object layout might actually
simplify the handling of an exception during object construction.
The remainder of the object (i.e., (1) above) might accomodate incremental
development, for example, new impl pointers could be added. Consider the
case where you start off with N data members, build and test the whole
project, and then add a new data member. Suppose the new data member is
accessed in only one translation unit; then only two translation units need
to re-compile instead of all that include the header X.h.
It is a bit far-fetched, perhaps, but maybe it could be pulled off. Not that
this doesn't contradict your statement about dynamic type above; it is as if
the same object may have servral internal type variants.
Regards, John.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: bo-staffan.lankinen@gbg.bonet.se ("Bo-Staffan Lankinen")
Date: Sun, 13 Jul 2003 17:49:59 +0000 (UTC) Raw View
> Why should there be "multiple invokations" of the placement
> new operator?
AFAICT, the C++ standard doesn't guarantee that the bytes in the
object-representation is a contiguous memory-chunk. As I interpret the
standard, when constructing an object in a new-expression, an implementation
is allowed to split up the bytes in 2 or more contiguous chunks, which are
allocated by separate invokations to an allocation function, 1.9/17 seems to
support that claim. If an object is split up in such a way, an object
created with the corresponding placement new-expression must also have that
object-representation.
> Besides, placement new simply passes its additional arguments
> to the allocation function. If you are so much concerned about
> keeping objects in contiguous memory, make your allocation
> function return one chunk _always_.
Yeah, but that would only work as long as the bytes in the
object-representation really is one contiguous memory-chunk.
Bo-Staffan
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: francis@robinton.demon.co.uk (Francis Glassborow)
Date: Sun, 13 Jul 2003 19:01:23 +0000 (UTC) Raw View
In article <bes3m3$8dq40$1@ID-47792.news.uni-berlin.de>, Bo-Staffan
Lankinen <bo-staffan.lankinen@gbg.bonet.se> writes
>AFAICT, the C++ standard doesn't guarantee that the bytes in the
>object-representation is a contiguous memory-chunk. As I interpret the
>standard, when constructing an object in a new-expression, an implementation
>is allowed to split up the bytes in 2 or more contiguous chunks, which are
>allocated by separate invokations to an allocation function, 1.9/17 seems to
>support that claim. If an object is split up in such a way, an object
>created with the corresponding placement new-expression must also have that
>object-representation.
Exactly how do you think that 1.9/17 supports this viewpoint. Of course
evaluating a new expression might result in more than one allocator
being called, the first one might fail, or the object's ctor might
include a new expression.
If a complete object could exist in non-contiguous then id would simply
be impossible for users to write placement new functions. If you think
otherwise it is up to you to demonstrate how this can be done. C++
allows the following:
void * raw = operator new(sizeof mytype);
mytype object = new(raw) mytype;
How do you propose that we implement that?
--
Francis Glassborow ACCU
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: cxl@volny.cz ("Mirek Fidler")
Date: Sun, 13 Jul 2003 20:23:18 +0000 (UTC) Raw View
> Exactly how do you think that 1.9/17 supports this viewpoint. Of
course
> evaluating a new expression might result in more than one allocator
> being called, the first one might fail, or the object's ctor might
> include a new expression.
>
> If a complete object could exist in non-contiguous then id would
simply
> be impossible for users to write placement new functions. If you think
> otherwise it is up to you to demonstrate how this can be done. C++
> allows the following:
>
> void * raw = operator new(sizeof mytype);
> mytype object = new(raw) mytype;
>
> How do you propose that we implement that?
Well, although I agree with you that multichunk complete objects are
not a good idea, I could imagine that implementation of
struct Alfa : Beta { int dummy; }
could be done as
struct Alfa {
Beta *base; // hidden member inserted by compiler
int dummy;
Alfa() {
base = compiler_generated_alloc_of_Beta(); }
~Alfa() {
compiler_generated_free_of_Beta(base);
}
};
Now, sizeof(Alfa) would be sizeof(Beta) + sizeof(int) (+
alignment...) and placement new would work. OTOH, it is still possible
that this is forbidden by some standard paragraph we have not considered
yet... (in fact, I hope it is :)
Of course, I can hardly imagine that some C++ implementation would
be as crazy....
Mirek
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: bo-staffan.lankinen@gbg.bonet.se ("Bo-Staffan Lankinen")
Date: Mon, 14 Jul 2003 01:59:01 +0000 (UTC) Raw View
> If a complete object could exist in non-contiguous then id would simply
> be impossible for users to write placement new functions. If you think
> otherwise it is up to you to demonstrate how this can be done. C++
> allows the following:
>
> void * raw = operator new(sizeof mytype);
> mytype object = new(raw) mytype;
Yes, syntactically it's correct, but as the standard currently is written, I
don't think it's guaranteed to be semantically correct.
> How do you propose that we implement that?
I don't propose a change to the current placement-new idiom. I'd like the
standard to guarantee the bytes in the object-representation to be one
contiguous memory-chunk, that would make me sleep much better at night.
Bo-Staffan
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: google@vandevoorde.com (Daveed Vandevoorde)
Date: Mon, 14 Jul 2003 05:34:18 +0000 (UTC) Raw View
francis@robinton.demon.co.uk (Francis Glassborow) wrote:
[...]
> void * raw = operator new(sizeof mytype);
> mytype object = new(raw) mytype;
>
> How do you propose that we implement that?
Say mytype contains a simple base occupying 32 bytes, and that it
adds a field of 8 bytes to that. A split object model could deem
the "object representation" to consist of the latter 8 bytes plus a
pointer to the 32 bytes (say, also 8 bytes). sizeof(mytype) is therefore
16 bytes, but note how the "whole object" contains 40 bytes of
information.
With this scenario (change the numbers however you like), the
first initialization allocates 16 bytes. For the second initialization,
I assume you meant (added asterisk):
mytype *object = new(raw) mytype;
This invokes the mytype constructor which can implictly allocate
a 40 byte chunk, set the aforementioned pointer to it, and call
the base constructor with that pointer.
Perhaps not efficient, but certainly standard conforming (and
perhaps even useful is some specialized environments).
Daveed
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: ron@sensor.com ("Ron Natalie")
Date: Mon, 14 Jul 2003 17:25:40 +0000 (UTC) Raw View
""Ron Natalie"" <ron@sensor.com> wrote in message news:3f0ee5e7$0$11866$9a6e19ea@news.newshosting.com...
>
> ""Bo Persson"" <bop2@telia.com> wrote in message news:K3wPa.19934$dP1.37278@newsc.telia.net...
>
> > No, the compiler can claim that unsigned char has the wrong alignment
> > for a T and refuse.
>
> Actually, it can even not refuse but blow up at runtime.
>
That doesn't read the way I intended it.
It should say "It can accept the program but blow up at runtime."
Alignment problems are not required to be diagnosed.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: andys@despammed.com (Andy Sawyer)
Date: Mon, 14 Jul 2003 20:02:48 +0000 (UTC) Raw View
In article <besurv$8jf09$1@ID-47792.news.uni-berlin.de>,
on Mon, 14 Jul 2003 01:59:01 +0000 (UTC),
bo-staffan.lankinen@gbg.bonet.se ("Bo-Staffan Lankinen") wrote:
> > void * raw = operator new(sizeof mytype);
> > mytype object = new(raw) mytype;
>
> Yes, syntactically it's correct
Only if mytype has a constructor that looks something like:
mytype( mytype * ); // or const mytype *
I suspect the second line should actually read:
mytype* object = new(raw) mytype;
Regards,
Andy S.
--
"Light thinks it travels faster than anything but it is wrong. No matter
how fast light travels it finds the darkness has always got there first,
and is waiting for it." -- Terry Pratchett, Reaper Man
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: bo-staffan.lankinen@gbg.bonet.se ("Bo-Staffan Lankinen")
Date: Mon, 14 Jul 2003 21:57:03 +0000 (UTC) Raw View
> Even so, the buffer being contiguous does not mean that
> the whole object must be contiguous; only the so-called
> "object representation" (standardese) must be contiguous.
Where do you find that requirement in the standard?
Bo-Staffan
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: markus.mauhart@nospamm.chello.at ("Markus Mauhart")
Date: Mon, 14 Jul 2003 21:58:31 +0000 (UTC) Raw View
"Daveed Vandevoorde" <google@vandevoorde.com> wrote ...
> argument it is given.
>
> Consider the following implementation strategy. Base class
> subobjects are allocated by constructors using a hidden
> built-in allocator, and the main ("derivation") chunk of the
> object just points to the base classes. sizeof(D) returns the
> number of bytes occupied by the main chunk of D only
> (including the pointers to base subobjects, but not including
> the base subobjects themselves).
>
> I believe that could be a correct C++ object model where the
> value of an object is not contained within a contiguous chunk
> of bytes.
I dont think so.
With any outstanding "::operator new" allocation IMHO I am
allowed to do the following ...
BYTE* p0 = (BYTE*) ::operator new(1024*1024);
....days
....and
....weeks
....later
int count = 1024*1024 / sizeof(ANY_X) ;//"ANY_X::ANY_X(..) throw()"
for (int i=0 ;i!=count ;++i)
::new ( (void*) (p0 + i*sizeof(ANY_X)) ) ANY_X(..);
//.... use the array ... I KNOW I dont need destructor ...
for (int i=0 ;i!=count ;++i)
::new ( (void*) (p0 + i*sizeof(ANY_X))) ANY_X(..);
//.... use the array ... I KNOW I dont need destructor ...
for (int i=0 ;i!=count ;++i)
::new ( (void*) (p0 + i*sizeof(ANY_X))) ANY_X(..);
//.... use the array ... I KNOW I dont need destructor ...
for (int i=0 ;i!=count ;++i)
::new ( (void*) (p0 + i*sizeof(ANY_X))) ANY_X(..);
.... and note, the 'hidden' allocation to allcoate the real memory for
the subobjects may not fail if your hypothetical c++ implementation
was conforming ... ANY_X-ctor is throw(), and AFAIK c++ implementations
generally may not create 'failures' at their will.
That iterated construction w/o destruction was surely a bit extreme, but
my point is that ::operator new(size_t) doesnt know in advance how much
memory it has to reserve for possibly later necessary hidden subobject
allocation. ::operator new() reasonably may be used to allocates MBs
of memory necessary for a STL-container-tuning small block allocator.
For example take Mr. Stroustrups decades old example for using and
implementing conforming class-specific allocation by suballocating
fixed size pieces out of greater blocks. This technique would be
non-portable if the above method (of using "::placement new" inside
the super-aligned byte-arrays we get as result of ::operator new)
was wrong ... and AFAIK such suballocation technique was one of the
very 1st things that Mr. Stroustrup used.
If my scenarios of ::operator new(size_t) usage are conforming, then
your hypothetical c++ implementation AFAICS would have to set aside
an incredibly (even infinite ?) large amount of extra memory to stay
conforming ... had such memory-destroying technology then anything
todo with C or C++ ?
If I was a member of the c++-committee, then I wouldnt spend a minute
of my time thinking about whether any change for c++0x might break such
"storage/=7" c++ implementation. Instead I would assume that anyone
interested enough in such a strange c++-simulator should simulate
continuous objects too; why not, when even the complete 25 year old
Intel "x86 machine" today is simulated by the engineers of Intel, AMD
and Transmeta, resulting in performance good enough for me and probably
also for you.
You are a c++ implementor: would you expect simulating continuous
objects to be an issue for you, when comparing it with 'simulating'
full featured templates, export and the rest of c++ ?
Regards,
Markus.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: v.Abazarov@attAbi.com ("Victor Bazarov")
Date: Tue, 15 Jul 2003 03:02:44 +0000 (UTC) Raw View
"Markus Mauhart" <markus.mauhart@nospamm.chello.at> wrote...
> "Daveed Vandevoorde" <google@vandevoorde.com> wrote ...
> > argument it is given.
> >
> > Consider the following implementation strategy. Base class
> > subobjects are allocated by constructors using a hidden
> > built-in allocator, and the main ("derivation") chunk of the
> > object just points to the base classes. sizeof(D) returns the
> > number of bytes occupied by the main chunk of D only
> > (including the pointers to base subobjects, but not including
> > the base subobjects themselves).
> >
> > I believe that could be a correct C++ object model where the
> > value of an object is not contained within a contiguous chunk
> > of bytes.
>
> I dont think so.
> With any outstanding "::operator new" allocation IMHO I am
> allowed to do the following ...
>
> BYTE* p0 = (BYTE*) ::operator new(1024*1024);
>
> ....days
> ....and
> ....weeks
> ....later
>
> int count = 1024*1024 / sizeof(ANY_X) ;//"ANY_X::ANY_X(..) throw()"
>
> for (int i=0 ;i!=count ;++i)
> ::new ( (void*) (p0 + i*sizeof(ANY_X)) ) ANY_X(..);
>
> //.... use the array ... I KNOW I dont need destructor ...
Here is my question: how do you KNOW? The Standard says that
you may reuse the storage if the lifetime of the object ended.
The lifetime ends with a call to the destructor. How is that
you don't need one?
> [...]
> If my scenarios of ::operator new(size_t) usage are conforming,
That would be my doubt too.
Victor
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: google@vandevoorde.com (Daveed Vandevoorde)
Date: Tue, 15 Jul 2003 03:23:24 +0000 (UTC) Raw View
markus.mauhart@nospamm.chello.at ("Markus Mauhart") wrote:
[...]
> With any outstanding "::operator new" allocation IMHO I am
> allowed to do the following ...
>
> BYTE* p0 = (BYTE*) ::operator new(1024*1024);
>
> ....days
> ....and
> ....weeks
> ....later
[Still running the same program though.]
> int count = 1024*1024 / sizeof(ANY_X) ;//"ANY_X::ANY_X(..) throw()"
>
> for (int i=0 ;i!=count ;++i)
> ::new ( (void*) (p0 + i*sizeof(ANY_X)) ) ANY_X(..);
>
> //.... use the array ... I KNOW I dont need destructor ...
>
> for (int i=0 ;i!=count ;++i)
> ::new ( (void*) (p0 + i*sizeof(ANY_X))) ANY_X(..);
>
> //.... use the array ... I KNOW I dont need destructor ...
>
> for (int i=0 ;i!=count ;++i)
> ::new ( (void*) (p0 + i*sizeof(ANY_X))) ANY_X(..);
>
> //.... use the array ... I KNOW I dont need destructor ...
>
> for (int i=0 ;i!=count ;++i)
> ::new ( (void*) (p0 + i*sizeof(ANY_X))) ANY_X(..);
>
> .... and note, the 'hidden' allocation to allcoate the real memory for
> the subobjects may not fail if your hypothetical c++ implementation
> was conforming ... ANY_X-ctor is throw(), and AFAIK c++ implementations
> generally may not create 'failures' at their will.
Sure they can: An implementation is required only to correctly
execute a program "within its resource limits" (1.4/2).
> That iterated construction w/o destruction was surely a bit extreme, but
> my point is that ::operator new(size_t) doesnt know in advance how much
> memory it has to reserve for possibly later necessary hidden subobject
> allocation. ::operator new() reasonably may be used to allocates MBs
> of memory necessary for a STL-container-tuning small block allocator.
I fail to see how that's relevant to my point that a a standard-compliant
implementation can involve discontinuous class objects.
> For example take Mr. Stroustrups decades old example for using and
> implementing conforming class-specific allocation by suballocating
> fixed size pieces out of greater blocks. This technique would be
> non-portable if the above method (of using "::placement new" inside
> the super-aligned byte-arrays we get as result of ::operator new)
> was wrong ... and AFAIK such suballocation technique was one of the
> very 1st things that Mr. Stroustrup used.
The implementation I suggested doesn't make that technique
"wrong." At worst it makes it less compelling for class deriving
from other classes (but even that is not clear cut).
> If my scenarios of ::operator new(size_t) usage are conforming, then
> your hypothetical c++ implementation AFAICS would have to set aside
> an incredibly (even infinite ?) large amount of extra memory to stay
> conforming ... had such memory-destroying technology then anything
> todo with C or C++ ?
See above regarding conformance: There is no problem here.
Also, have you heard of garbage collecting allocators? The base
class allocator would be a natural candidate for such an allocator
in the scheme I described.
> If I was a member of the c++-committee, then I wouldnt spend a minute
> of my time thinking about whether any change for c++0x might break such
> "storage/=7" c++ implementation.
I don't understand the "storage/=7" phrase, but I have often thought
about such implementations (and I attend committee meetings as an
employee of a company that is a member). In particular, I have thought
quite a bit about C++ interpreters, and in that context I considered
using such an object model.
> Instead I would assume that anyone
> interested enough in such a strange c++-simulator should simulate
> continuous objects too; why not, when even the complete 25 year old
> Intel "x86 machine" today is simulated by the engineers of Intel, AMD
> and Transmeta, resulting in performance good enough for me and probably
> also for you.
I don't know how this is related to the discussion.
I was not talking about simulating anything. Instead,
I proposed a valid C++ object model. There is nothing
simulated about it.
> You are a c++ implementor: would you expect simulating continuous
> objects to be an issue for you, when comparing it with 'simulating'
> full featured templates, export and the rest of c++ ?
I don't understand the question. I never talked about
simulation. I _did_ consider the object model I described
(in the past) for a C++ interpreter because I thought it
might work better with an allocator used in that
interpreted environment.
Daveed
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: markus.mauhart@nospamm.chello.at ("Markus Mauhart")
Date: Tue, 15 Jul 2003 15:35:39 +0000 (UTC) Raw View
""Victor Bazarov"" <v.Abazarov@attAbi.com> wrote ...
>
> "Markus Mauhart" <markus.mauhart@nospamm.chello.at> wrote...
> >
> > I dont think so.
> > With any outstanding "::operator new" allocation IMHO I am
> > allowed to do the following ...
> >
> > BYTE* p0 = (BYTE*) ::operator new(1024*1024);
> >
> > int count = 1024*1024 / sizeof(ANY_X) ;//"ANY_X::ANY_X(..) throw()"
> >
> > for (int i=0 ;i!=count ;++i)
> > ::new ( (void*) (p0 + i*sizeof(ANY_X)) ) ANY_X(..);
> >
> > //.... use the array ... I KNOW I dont need destructor ...
>
> Here is my question: how do you KNOW? The Standard says that
> you may reuse the storage if the lifetime of the object ended.
> The lifetime ends with a call to the destructor. How is that
> you don't need one?
"I KNOW" means "I dont need want dtor code to be executed" and
"I know that my program will never refer to the previous objects".
But it doesnt mean "I know c++ allows this".
The case of reusing the memory w/o calling dtors is and was not
my main argument against the outlined c++ implementation, this
special case happend during writing, and I was aware that this
might introduce undefined behaviour. But your argument did not
say explicitely nor convince me that calling placement new twice
on the same location introduces UB ... so if you or sombody else
are sure that this is the case, then please provide more concrete
pointers into the standard.
> > [...]
> > If my scenarios of ::operator new(size_t) usage are conforming,
>
> That would be my doubt too.
Please for now ignore the above *special case* of forgetting to call dtors.
> > BYTE* p0 = (BYTE*) ::operator new(1024*1024);
> >
> > int count = 1024*1024 / sizeof(ANY_X) ;//"ANY_X::ANY_X(..) throw()"
> >
> > for (int i=0 ;i!=count ;++i)
> > ::new ( (void*) (p0 + i*sizeof(ANY_X)) ) ANY_X(..);
Is this allowed ?
Is it also allowed for any result of malloc() ?
Both happens in stdlib++'s std::allocator, boost's pool uses it too.
Do you agree that then, with Daveed's sample object model, most calls
to ::operator new(size_t) or malloc() would have to set aside a big,
maybe even infinite amount of memory ?
Regards,
Markus.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: google@vandevoorde.com (Daveed Vandevoorde)
Date: Tue, 15 Jul 2003 23:49:59 +0000 (UTC) Raw View
bo-staffan.lankinen@gbg.bonet.se ("Bo-Staffan Lankinen") wrote in message news:<bes3oe$86ph7$1@ID-47792.news.uni-berlin.de>...
> > Even so, the buffer being contiguous does not mean that
> > the whole object must be contiguous; only the so-called
> > "object representation" (standardese) must be contiguous.
>
> Where do you find that requirement in the standard?
I believe it's implicit in the requirements for sizeof (5.3.3/1,2)
that sizeof (T[N]) == N*sizeof(T). This doesn't make continuity
of the object representation a requirement, but I cannot think
of a discontinous model for that part (while I can for the "whole
object").
Daveed
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: v.Abazarov@attAbi.com ("Victor Bazarov")
Date: Tue, 15 Jul 2003 23:50:52 +0000 (UTC) Raw View
"Markus Mauhart" <markus.mauhart@nospamm.chello.at> wrote...
> ""Victor Bazarov"" <v.Abazarov@attAbi.com> wrote ...
> >
> > "Markus Mauhart" <markus.mauhart@nospamm.chello.at> wrote...
> > >
> > > I dont think so.
> > > With any outstanding "::operator new" allocation IMHO I am
> > > allowed to do the following ...
> > >
> > > BYTE* p0 = (BYTE*) ::operator new(1024*1024);
> > >
> > > int count = 1024*1024 / sizeof(ANY_X) ;//"ANY_X::ANY_X(..) throw()"
> > >
> > > for (int i=0 ;i!=count ;++i)
> > > ::new ( (void*) (p0 + i*sizeof(ANY_X)) ) ANY_X(..);
> > >
> > > //.... use the array ... I KNOW I dont need destructor ...
> >
> > Here is my question: how do you KNOW? The Standard says that
> > you may reuse the storage if the lifetime of the object ended.
> > The lifetime ends with a call to the destructor. How is that
> > you don't need one?
>
> "I KNOW" means "I dont need want dtor code to be executed" and
> "I know that my program will never refer to the previous objects".
> But it doesnt mean "I know c++ allows this".
>
> The case of reusing the memory w/o calling dtors is and was not
> my main argument against the outlined c++ implementation, this
> special case happend during writing, and I was aware that this
> might introduce undefined behaviour. But your argument did not
> say explicitely nor convince me that calling placement new twice
> on the same location introduces UB ... so if you or sombody else
> are sure that this is the case, then please provide more concrete
> pointers into the standard.
Based on 3.8: the lifetime ends when a non-trivial destructor is
called or when the storage is released or reused. If your object
(due to a specific object model Daveed described) ends its life,
the storage for the base classes (which are allocated elsewhere)
has to be released. How? I don't know. Ask Daveed.
> > > BYTE* p0 = (BYTE*) ::operator new(1024*1024);
> > >
> > > int count = 1024*1024 / sizeof(ANY_X) ;//"ANY_X::ANY_X(..) throw()"
> > >
> > > for (int i=0 ;i!=count ;++i)
> > > ::new ( (void*) (p0 + i*sizeof(ANY_X)) ) ANY_X(..);
>
> Is this allowed ?
I guess that it is. I assume that BYTE in your case is a char.
> Is it also allowed for any result of malloc() ?
I am not sure I understand this. 'malloc' only allocates 'chars',
IIRC. So, probably, yes.
> Both happens in stdlib++'s std::allocator, boost's pool uses it too.
>
> Do you agree that then, with Daveed's sample object model, most calls
> to ::operator new(size_t) or malloc() would have to set aside a big,
> maybe even infinite amount of memory ?
If I understand what Daveed was talking about, your schema will
have "gaps" in the allocated 'p0' for the base classes. You will
have fewer 'ANY_X' objects allocated than the "real size" of any
ANY_X object is. "sizeof" reports the number of bytes taken by
all subobjects combined. Given that the most derived object will
contain pointers to base class objects, every pointer will waste
sizeof(void*) in the entire object (because it has to be accounted
for). I am not seeing any "infinite" amounts of memory here.
Victor
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: markus.mauhart@nospamm.chello.at ("Markus Mauhart")
Date: Tue, 15 Jul 2003 23:51:10 +0000 (UTC) Raw View
"Daveed Vandevoorde" <google@vandevoorde.com> wrote ...
> markus.mauhart@nospamm.chello.at ("Markus Mauhart") wrote:
> [...]
> > With any outstanding "::operator new" allocation IMHO I am
> > allowed to do the following ...
> >
> > BYTE* p0 = (BYTE*) ::operator new(1024*1024);
> >
> > ....days
> > ....and
> > ....weeks
> > ....later
>
> [Still running the same program though.]
yes ;-)
> > int count = 1024*1024 / sizeof(ANY_X) ;//"ANY_X::ANY_X(..) throw()"
> >
> > for (int i=0 ;i!=count ;++i)
> > ::new ( (void*) (p0 + i*sizeof(ANY_X)) ) ANY_X(..);
> >
> > [...optionally reusing memory w/o calling dtor]
Btw, do you think that this kind of 'reusing' is generally allowed ?
Or would your c++ interpreter in its debug mode say "the program enters
undefined behaviour" ?
> > .... and note, the 'hidden' allocation to allcoate the real memory for
> > the subobjects may not fail if your hypothetical c++ implementation
> > was conforming ... ANY_X-ctor is throw(), and AFAIK c++ implementations
> > generally may not create 'failures' at their will.
>
> Sure they can: An implementation is required only to correctly
> execute a program "within its resource limits" (1.4/2).
Yes, but IMHO you wouldnt be proud about the resource limits of your
hypothetic c++ implementation, it would be no pleassure for you to
document it.
> I fail to see how that's relevant to my point that a a standard-compliant
> implementation can involve discontinuous class objects.
IIRC your point and the intent of presenting your sample object model
was not to proof that discontinuous class objects are allowed, but to
show that allowing them is usefull.
My point is that if this hypothetic c++ interpreter is your best argument
for allowing discontinuous class objects, then this is a strong hint for
me that allowing them is a useless complication of the c++ object model.
> > If my scenarios of ::operator new(size_t) usage are conforming, then
> > your hypothetical c++ implementation AFAICS would have to set aside
> > an incredibly (even infinite ?) large amount of extra memory to stay
> > conforming ... had such memory-destroying technology then anything
> > todo with C or C++ ?
>
> See above regarding conformance: There is no problem here.
Cause the requirements concerning memory & CPU consumption you choose
for your hypothetic c++ interpreter are completely irregular.
> Also, have you heard of garbage collecting allocators? The base
> class allocator would be a natural candidate for such an allocator
> in the scheme I described.
I've heard about that terms and followed some discussions, but the
older I grow the less reason for garbage collection in c++ I see.
But now you hit me on my weak point: "garbage collecting allocator",
shall this be a justification to add an additional requirement to
20.1.5 saying "you may not use the result of allocate() inside
placement new expressions or destructor calls, instead you have
to use allocator.construct()/destroy()", so turning allocators
into object factories ?
> > If I was a member of the c++-committee, then I wouldnt spend a minute
> > of my time thinking about whether any change for c++0x might break such
> > "storage/=7" c++ implementation.
>
> I don't understand the "storage/=7" phrase
This phrase referres to my assumption that your sample implementation
required quite a multiple (-> "7"; or infinite ?) of the amount of memory
than any c++ implementation currently used for production code.
> > You are a c++ implementor: would you expect simulating continuous
> > objects to be an issue for you, when comparing it with 'simulating'
> > full featured templates, export and the rest of c++ ?
>
> I don't understand the question. I never talked about
> simulation. I _did_ consider the object model I described
> (in the past) for a C++ interpreter because I thought it
> might work better with an allocator used in that
> interpreted environment.
My question to you as one of the most successful c++ implementors
is whether the c++ standard, IF IN DOUBT, should pay more attention
to ease creating of future exotic conforming c++ implementations
like your outlined c++ interpreter, or whether it instead should
pay more attention to ease understanding and using the c++ programming
language, especially its object model, for current c++ users like me
and Mirek Fidler, like the readers of this newsgroup, like the members
of the c++ committee, like the other c++ implementors.
The fact that (in this forum) the only thinkable possible usage
of discontinuous c++ objects is your former idea for a c++
interpreter, and that nevertheless many intelligent people felt
a need to spend their valuable time discussing again the c++ object
model, as it has been discussed many times before, is a strong hint
for me that todays provission for future "discontinuous c++ objects"
is IN DOUBT.
Do you think that an additional requirement for "continuous c++
objects" would be a technical barrier for your future efforts
producing excellent c++ implementations, or even for the future
success of c++ ?
I dont think so.
Regards,
Markus.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: markus.mauhart@nospamm.chello.at ("Markus Mauhart")
Date: Wed, 16 Jul 2003 16:47:40 +0000 (UTC) Raw View
""Victor Bazarov"" <v.Abazarov@attAbi.com> wrote ...
> "Markus Mauhart" <markus.mauhart@nospamm.chello.at> wrote...
> > ""Victor Bazarov"" <v.Abazarov@attAbi.com> wrote ...
> > >
> > > Here is my question: how do you KNOW? The Standard says that
> > > you may reuse the storage if the lifetime of the object ended.
> > > The lifetime ends with a call to the destructor. How is that
> > > you don't need one?
> >
> > [...]
> >
> > The case of reusing the memory w/o calling dtors is and was not
> > my main argument against the outlined c++ implementation, this
> > special case happend during writing, and I was aware that this
> > might introduce undefined behaviour. But your argument did not
> > say explicitely nor convince me that calling placement new twice
> > on the same location introduces UB ... so if you or sombody else
> > are sure that this is the case, then please provide more concrete
> > pointers into the standard.
>
> Based on 3.8: the lifetime ends when a non-trivial destructor is
> called or when the storage is released or reused.
Thanks for the more details here. This is now significantly different
from your previous opinion "The Standard says that you may reuse the
storage if the lifetime of the object ended. The lifetime ends with a
call to the destructor.".
> If your object (due to a specific object model Daveed described) ends
> its life, the storage for the base classes (which are allocated
> elsewhere) has to be released. How? I don't know. Ask Daveed.
Neither I know it ;-) IMHO Daveed knows a lot about this problem
and about possible strategies to tackle it.
Our current consensus seems to be that reusing w/o dtor is allowed
(not UB), but with some object models/c++-implementations under
discussion this practise would generate serious resource leaks.
> If I understand what Daveed was talking about, your schema will
> have "gaps" in the allocated 'p0' for the base classes. You will
> have fewer 'ANY_X' objects allocated than the "real size" of any
> ANY_X object is. "sizeof" reports the number of bytes taken by
> all subobjects combined. Given that the most derived object will
> contain pointers to base class objects, every pointer will waste
> sizeof(void*) in the entire object (because it has to be accounted
> for).
With 'waste' I meant the necessity to reserve enough address space
(besides the 1024*1024 bytes as requested) and page file space, so that
later a possible ANY_X-creation needing large hidden subobject-allocation
may succeed. The factor will be up to the largest ...
'sizeof(T)/hidden_sizeof(T)'
.... for any T in the program.
> I am not seeing any "infinite" amounts of memory here.
You are probably right. I saw "infinite" as the unavoidable consequence
when creating AGAIN objects w/o prior dtor; but now I think that during
the "n'th object creation" the implementation gets enough information
to reclaim all non-destructed resources of the "(n-1)'th creation" ...
this doesnt make the c++ implementation easier, but this way it can
reliably avoid to leak infinite resources.
Regards,
Markus.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: markus.mauhart@nospamm.chello.at ("Markus Mauhart")
Date: Wed, 16 Jul 2003 21:28:34 +0000 (UTC) Raw View
"Daveed Vandevoorde" <google@vandevoorde.com> wrote ...
> bo-staffan.lankinen@gbg.bonet.se ("Bo-Staffan Lankinen") wrote...
> > > Even so, the buffer being contiguous does not mean that
> > > the whole object must be contiguous; only the so-called
> > > "object representation" (standardese) must be contiguous.
> >
> > Where do you find that requirement in the standard?
>
> I believe it's implicit in the requirements for sizeof (5.3.3/1,2)
> that sizeof (T[N]) == N*sizeof(T). This doesn't make continuity
> of the object representation a requirement, but I cannot think
> of a discontinous model for that part (while I can for the "whole
> object").
Doesnt the definition of "object representation" (OR) explicitely say
that it is continuous:
3.9,4:
The object representation of an object of type T is the sequence of
N unsigned char objects taken up by the object of type T, where N
equals sizeof(T).
(I have been told that "where N equals sizeof(T)" is not part of OR's
definition, instead more a 'pointer' to the later defined 'name'
for this sequence' lenght.)
sequence <=> continuous" ?
Regards,
Markus.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: google@vandevoorde.com (Daveed Vandevoorde)
Date: Thu, 17 Jul 2003 01:59:25 +0000 (UTC) Raw View
markus.mauhart@nospamm.chello.at ("Markus Mauhart") wrote:
> "Daveed Vandevoorde" <google@vandevoorde.com> wrote ...
> > markus.mauhart@nospamm.chello.at ("Markus Mauhart") wrote:
> > [...]
> > > With any outstanding "::operator new" allocation IMHO I am
> > > allowed to do the following ...
> > >
> > > BYTE* p0 = (BYTE*) ::operator new(1024*1024);
> > >
> > > ....days
> > > ....and
> > > ....weeks
> > > ....later
> >
> > [Still running the same program though.]
>
> yes ;-)
>
> > > int count = 1024*1024 / sizeof(ANY_X) ;//"ANY_X::ANY_X(..) throw()"
> > >
> > > for (int i=0 ;i!=count ;++i)
> > > ::new ( (void*) (p0 + i*sizeof(ANY_X)) ) ANY_X(..);
> > >
> > > [...optionally reusing memory w/o calling dtor]
>
> Btw, do you think that this kind of 'reusing' is generally allowed ?
> Or would your c++ interpreter in its debug mode say "the program enters
> undefined behaviour" ?
Yes, it's allowed. (Resource leakage is not undefined behavior;
sometimes it's not even a bug ;-).
> > > .... and note, the 'hidden' allocation to allcoate the real memory for
> > > the subobjects may not fail if your hypothetical c++ implementation
> > > was conforming ... ANY_X-ctor is throw(), and AFAIK c++ implementations
> > > generally may not create 'failures' at their will.
> >
> > Sure they can: An implementation is required only to correctly
> > execute a program "within its resource limits" (1.4/2).
>
> Yes, but IMHO you wouldnt be proud about the resource limits of your
> hypothetic c++ implementation, it would be no pleassure for you to
> document it.
Not a pleasure, but not necessarily a shame either.
>
> > I fail to see how that's relevant to my point that a a standard-compliant
> > implementation can involve discontinuous class objects.
>
> IIRC your point and the intent of presenting your sample object model
> was not to proof that discontinuous class objects are allowed, but to
> show that allowing them is usefull.
My main point was really that such models can be standard-compliant:
That is a statement that can be objectively verified. A sub-issue is that
they might have uses, which is somewhat of a subjective statement.
> My point is that if this hypothetic c++ interpreter is your best argument
> for allowing discontinuous class objects, then this is a strong hint for
> me that allowing them is a useless complication of the c++ object model.
Oh, there are other arguments. For example, it enables more flexibility
in achieving release-to-release binary compatibility (RRBC) with C++
libraries (a difficult problem).
> > > If my scenarios of ::operator new(size_t) usage are conforming, then
> > > your hypothetical c++ implementation AFAICS would have to set aside
> > > an incredibly (even infinite ?) large amount of extra memory to stay
> > > conforming ... had such memory-destroying technology then anything
> > > todo with C or C++ ?
> >
> > See above regarding conformance: There is no problem here.
>
> Cause the requirements concerning memory & CPU consumption you choose
> for your hypothetic c++ interpreter are completely irregular.
By "regarding conformance" I meant just that: Memory requirements don't
really play into whether or not the implementation is conformant (which
I though contradicted your statement). They do play into the value of the
implementation, but that's another issue.
> > Also, have you heard of garbage collecting allocators? The base
> > class allocator would be a natural candidate for such an allocator
> > in the scheme I described.
>
> I've heard about that terms and followed some discussions, but the
> older I grow the less reason for garbage collection in c++ I see.
>
> But now you hit me on my weak point: "garbage collecting allocator",
> shall this be a justification to add an additional requirement to
> 20.1.5 saying "you may not use the result of allocate() inside
> placement new expressions or destructor calls, instead you have
> to use allocator.construct()/destroy()", so turning allocators
> into object factories ?
I'm not sure I follow. I'm only talking about an internal allocator/
collector for base class subobjects. In some ways this is very similar
to automatic allocation/deallocation for local variables, except the
pattern is much less regular. However, it does not change the
library interfaces.
> > > If I was a member of the c++-committee, then I wouldnt spend a minute
> > > of my time thinking about whether any change for c++0x might break such
> > > "storage/=7" c++ implementation.
> >
> > I don't understand the "storage/=7" phrase
>
> This phrase referres to my assumption that your sample implementation
> required quite a multiple (-> "7"; or infinite ?) of the amount of memory
> than any c++ implementation currently used for production code.
More memory, yes. It depends on the application, but I suspect most
applications would see less than 100% increase in memory use. (Perhaps
the most frustrating increase is for optimized empty bases.)
> > > You are a c++ implementor: would you expect simulating continuous
> > > objects to be an issue for you, when comparing it with 'simulating'
> > > full featured templates, export and the rest of c++ ?
> >
> > I don't understand the question. I never talked about
> > simulation. I _did_ consider the object model I described
> > (in the past) for a C++ interpreter because I thought it
> > might work better with an allocator used in that
> > interpreted environment.
>
> My question to you as one of the most successful c++ implementors
> is whether the c++ standard, IF IN DOUBT, should pay more attention
> to ease creating of future exotic conforming c++ implementations
> like your outlined c++ interpreter, or whether it instead should
> pay more attention to ease understanding and using the c++ programming
> language, especially its object model, for current c++ users like me
> and Mirek Fidler, like the readers of this newsgroup, like the members
> of the c++ committee, like the other c++ implementors.
I don't entirely understand the question. However, I do think that
it's always useful to keep our minds open about implementation
techniques. In some ways, a completely standardized object model
is highly attractive, because you can easily program to its internals.
However, in the long run you are likely miss out on some interesting
alternative techniques. In practice, it is hard to tighten the existing
constraints on the object model because there are already several
such models in wide use.
> The fact that (in this forum) the only thinkable possible usage
> of discontinuous c++ objects is your former idea for a c++
> interpreter, and that nevertheless many intelligent people felt
> a need to spend their valuable time discussing again the c++ object
> model, as it has been discussed many times before, is a strong hint
> for me that todays provission for future "discontinuous c++ objects"
> is IN DOUBT.
I think you're may be jumping too quickly to conclusions.
I mentioned the advantages of such a mode for RRBC.
For some applications it might be interesting to explore
the possibilities of dynamic base reconfiguration.
> Do you think that an additional requirement for "continuous c++
> objects" would be a technical barrier for your future efforts
> producing excellent c++ implementations, or even for the future
> success of c++ ?
> I dont think so.
Maybe, but I don't think such a requirement would have a positive effect
either. What would it buy the implementor. At least, I can conjecture
about uses for a more dynamic object model.
Daveed
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: markus.mauhart@nospamm.chello.at ("Markus Mauhart")
Date: Fri, 18 Jul 2003 02:42:04 +0000 (UTC) Raw View
"Daveed Vandevoorde" <google@vandevoorde.com> wrote ...
> markus.mauhart@nospamm.chello.at ("Markus Mauhart") wrote:
> > "Daveed Vandevoorde" <google@vandevoorde.com> wrote ...
> > > markus.mauhart@nospamm.chello.at ("Markus Mauhart") wrote:
> > > [...]
> > Btw, do you think that this kind of 'reusing' is generally allowed ?
> > Or would your c++ interpreter in its debug mode say "the program enters
> > undefined behaviour" ?
>
> Yes, it's allowed. (Resource leakage is not undefined behavior;
> sometimes it's not even a bug ;-).
thanks, I'm allways glad when I can avoid a possible roundtrip through the
standard ;-)
> > > > .... and note, the 'hidden' allocation to allcoate the real memory for
> > > > the subobjects may not fail if your hypothetical c++ implementation
> > > > was conforming ... ANY_X-ctor is throw(), and AFAIK c++ implementations
> > > > generally may not create 'failures' at their will.
> > >
> > > Sure they can: An implementation is required only to correctly
> > > execute a program "within its resource limits" (1.4/2).
> >
> > Yes, but IMHO you wouldnt be proud about the resource limits of your
> > hypothetic c++ implementation, it would be no pleassure for you to
> > document it.
>
> Not a pleasure, but not necessarily a shame either.
no doubt.
> > > I fail to see how that's relevant to my point that a a standard-compliant
> > > implementation can involve discontinuous class objects.
> >
> > IIRC your point and the intent of presenting your sample object model
> > was not to proof that discontinuous class objects are allowed, but to
> > show that allowing them is usefull.
>
> My main point was really that such models can be standard-compliant:
> That is a statement that can be objectively verified. A sub-issue is that
> they might have uses, which is somewhat of a subjective statement.
well, your example IMHO in this discussion was the only 'proof' of reality
for discontinuous layouts, and with your name behind it, and you not mentioning
a single disadvantage for it, IMHO it was a bit too much unjustified PR for
such layouts.
> > My point is that if this hypothetic c++ interpreter is your best argument
> > for allowing discontinuous class objects, then this is a strong hint for
> > me that allowing them is a useless complication of the c++ object model.
>
> Oh, there are other arguments. For example, it enables more flexibility
> in achieving release-to-release binary compatibility (RRBC) with C++
> libraries (a difficult problem).
ok, but still not convinced. What about other solutions like abstract classes,
COM, CORBA, or other languages ? Needing so much "binary compatibility" sounds
allmost so as if someone had made serious design errors ... unnecessary low
level interdependencies ;-)
> > But now you hit me on my weak point: "garbage collecting allocator",
> > shall this be a justification to add an additional requirement to
> > 20.1.5 saying "you may not use the result of allocate() inside
> > placement new expressions or destructor calls, instead you have
> > to use allocator.construct()/destroy()", so turning allocators
> > into object factories ?
>
> I'm not sure I follow. I'm only talking about an internal allocator/
> collector for base class subobjects. In some ways this is very similar
> to automatic allocation/deallocation for local variables, except the
> pattern is much less regular. However, it does not change the
> library interfaces.
Ok.
> More memory, yes. It depends on the application, but I suspect most
> applications would see less than 100% increase in memory use. (Perhaps
> the most frustrating increase is for optimized empty bases.)
isnt a main problem of this model that a simple implementation would
really consume too much resources (cpu, cache, memory), especially
when compared with other languages that like to compete with c++,
while finding 'the right' combination of the 100 tricks and strategies
you probably have in your bag is still an open question.
> In some ways, a completely standardized object model
> is highly attractive, because you can easily program to its internals.
> However, in the long run you are likely miss out on some interesting
> alternative techniques.
IMHO it is much more likely for us to miss interesting alternative
techniques being used or developed far away from ISO+IEC+14882-1998,
than missing such techniques that only rely on some "strangeness"
of ISO+IEC+14882-1998 like possibly discontinuous objects.
If I was on the hunt for a hopefully revolutionary and interesting new
"programming language facility", then I wouldnt start with 2MB of
ISO+IEC+14882-1998.pdf, trying to find some peephole of flexibility in it.
Take MS's marriage of the completely different languages CLI and plain
old (continuous;-) c++ via "managed c++", providing a firewall for all my
old low level "continuous c++" code. IMHO this is a much more rewarding
startingpoint for analysis and study for possible future c++ *extensions*,
than trying to turn every bit of uncertainty of current c++ into new
features.
Remove discontinous objects; dont copy and extend C99' details w.r.t.
indeterminate values and such, instead try to REMOVE it ... or is there
any current CPU that cant automatically catch all access to uninitialized
builtins, so why not turn indeterminate values and trap representations
into civilized unspecified values ? E.g. boost/stdext::weak_ptr is in danger
to contain an unreadable and uncopyable indeterminate pointer value.
> In practice, it is hard to tighten the existing constraints on the
> object model because there are already several such models in wide use.
Wide use of discontinous c++ object layouts in non-academic and
non-experimental fields, still actively maintained ? Any pointer ?
> > The fact that (in this forum) the only thinkable possible usage
> > of discontinuous c++ objects is your former idea for a c++
> > interpreter, and that nevertheless many intelligent people felt
> > a need to spend their valuable time discussing again the c++ object
> > model, as it has been discussed many times before, is a strong hint
> > for me that todays provission for future "discontinuous c++ objects"
> > is IN DOUBT.
>
> I think you're may be jumping too quickly to conclusions.
> I mentioned the advantages of such a mode for RRBC.
> For some applications it might be interesting to explore
> the possibilities of dynamic base reconfiguration.
possibly, but now is 2003, and it can happen that we both have long
grey beards whilst c++ discontinous object models still havnt payed
back what provision for them IMO daily costs.
> > Do you think that an additional requirement for "continuous c++
> > objects" would be a technical barrier for your future efforts
> > producing excellent c++ implementations, or even for the future
> > success of c++ ?
> > I dont think so.
>
> Maybe, but I don't think such a requirement would have a positive
> effect either. What would it buy the implementor.
ahh ... you really meant 'implementor', not 'programmer' ?-)
E.g. for you: assuming a contionuous c++ object model. If a discontinous
model really had such potential, you had much more freedom when 1st
exploring it outside the 1000 rules of c++. If you then really find a
diamond , then make the best of it: inside current c++, or with
"c++0x-discontinous", or with "EDG-managed c++".
OTOH starting outside the straight jacket of c++ you also had better
chances to quickly find out when there is no diamond worth the troubles.
Btw, do Java or CLI implementations internally use discontinuous object
models, or Eiffel.NET ?
IMO a simpler object model is a simpler language, and this pays every
day we use the language or need to look into the standard. And saves
a lot of questions in the newsgroups.
> At least, I can conjecture about uses for a more dynamic object model.
No reasons to stop that.
Regards,
Markus.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: cxl@volny.cz ("Mirek Fidler")
Date: Fri, 11 Jul 2003 01:36:35 +0000 (UTC) Raw View
> Operator new uses whatever the allocation function returns. If
> the allocation function returns contiguous memory, so will be
> the object.
Well, reading this, perhaps there is a confusion about what I mean
by contiguous memory. What I am asking for is whether C++ allows storage
chunks of several objects to be 'mixed' in memory, like
---|A part1|---|B part1|A part2|----|B part2|----
Also can be explained as whether "(size_t)&x - (size_t)(Base *)this"
for each member variable "x" is constant for any instance.
I am of course not interested in alignment padding or unused chunks
of memory within sizeof(T).
Mirek
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: v.Abazarov@attAbi.com ("Victor Bazarov")
Date: Fri, 11 Jul 2003 01:37:52 +0000 (UTC) Raw View
"Bo-Staffan Lankinen" <bo-staffan.lankinen@gbg.bonet.se> wrote...
> > I am not sure what you mean. How would that matter? Every
> > 'new' operator works with memory address returned to it by
> > the allocation function (3.7.3.1), placement new is not in
> > any way different, it just passes extra arguments to that
> > allocation function. It's the job of the allocation function
> > to recognise that the memory is split into pieces and not to
> > use it, I suppose.
>
> The placement new idiom is based on the object representation being one
> contiguous memory-chunk. If the address of such a memory-chunk is passed
to
> a placement new expression and there are multiple invokations of the
> placement new operator, different parts of the object will reside in the
> same memory location because the placement new operator returns the
address
> of the memory-chunk for all the invokations.
Why should there be "multiple invokations" of the placement
new operator?
Besides, placement new simply passes its additional arguments
to the allocation function. If you are so much concerned about
keeping objects in contiguous memory, make your allocation
function return one chunk _always_. Again, I haven't seen any
explanation yet as to why _allowing_ to keep objects spread in
memory interferes with anything else.
V
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: v.Abazarov@attAbi.com ("Victor Bazarov")
Date: Fri, 11 Jul 2003 01:38:12 +0000 (UTC) Raw View
"John D. Hickin" <hickin@cam.org> wrote...
> ----- Original Message -----
> From: ""Mirek Fidler"" <cxl@volny.cz>
>
> > I thing operator new does. Custom allocators do too. That said, I
> > really do not understand how sizeof could return total number of bytes
> > of object representation, object would be splitted through the memory
> > and in the same time new would work while, at least, not wasting memory.
> > (See e.g. 5.3.4).
> >
>
> But who says that it can't waste memory? It might have to be so...
>
> If you can still get hold of the cfront compiler (or perhaps one having a
> special mode that emulates cfront's idiosyncracies) you might see that an
> inheritance in the form of a kite (i.e., _diamond of death_ with a pig
tail)
> actually has two instances of the virtual base; the generated code only
> references (in consistent fashion) one of the virtual base class
instances.
> Certainly a waste of space, probably a bug, but it never really caused
> problems.
>
> I do think, however, that it was the intent of the standard to:
Intent? There must have been a reason, then, why that intent
didn't make it into the Standard...
> - stipulate that objects shall occupy contiguous storage
I haven't seen a proven need for this yet. What other parts
of the Standard would require this? And please don't just say
"placement new". Please, do explain why whatever you claim to
require contiguous storage does require it.
> - all instances of a given type shall have the same size and layout
> - aside from holes required because of alignment requirements, allow that
> wasted space could be minimized
I think that those requirements would be unnecessarily strict.
Thank you.
Victor
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: cxl@volny.cz ("Mirek Fidler")
Date: Fri, 11 Jul 2003 16:06:03 +0000 (UTC) Raw View
> function return one chunk _always_. Again, I haven't seen any
> explanation yet as to why _allowing_ to keep objects spread in
> memory interferes with anything else.
Perhaps I start to understand you. What you are claiming is that C++
standard allows different layout for automatic/static objects and for
objects on heap ? :)
Mirek
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: bop2@telia.com ("Bo Persson")
Date: Fri, 11 Jul 2003 16:06:05 +0000 (UTC) Raw View
"James Dennett" <jdennett@acm.org> skrev i meddelandet
news:YK7Pa.609$P83.92@fed1read02...
> Victor Bazarov wrote:
> > "Bo-Staffan Lankinen" <bo-staffan.lankinen@gbg.bonet.se> wrote...
> >
> >>>What does it matter whether the bytes are contiguous or spread
around?
> >>>If you want to copy the object using memcpy or memmove you may
only
> >>>do that with POD. Any other operation does not require the
object to
> >>>be in contiguous memory, does it?
> >>
> >>I can matter when constructing with placement new.
> >
> >
> > I am not sure what you mean. How would that matter?
>
> struct T { ... };
> unsigned char buffer[sizeof(T)];
> new (static_cast<void*>(p)) T;
>
> This must construct a T object in the buffer. It has
> to assume that the buffer is contiguous, and use it.
No, the compiler can claim that unsigned char has the wrong alignment
for a T and refuse.
If you use malloc(sizeof(T)) the returned block, if any, will be
suitable. However malloc is specifically allowed to return a larger
block than requested, to make it suitably aligned.
Bo Persson
bop2@telia.com
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: google@vandevoorde.com (Daveed Vandevoorde)
Date: Fri, 11 Jul 2003 17:52:44 +0000 (UTC) Raw View
jdennett@acm.org (James Dennett) wrote:
> > "Bo-Staffan Lankinen" <bo-staffan.lankinen@gbg.bonet.se> wrote...
> >
> >>>What does it matter whether the bytes are contiguous or spread around?
> >>>If you want to copy the object using memcpy or memmove you may only
> >>>do that with POD. Any other operation does not require the object to
> >>>be in contiguous memory, does it?
> >>
> >>I can matter when constructing with placement new.
> >
> >
> > I am not sure what you mean. How would that matter?
>
> struct T { ... };
> unsigned char buffer[sizeof(T)];
> new (static_cast<void*>(p)) T;
>
> This must construct a T object in the buffer. It has
> to assume that the buffer is contiguous, and use it.
Well, it doesn't actually have to work in general because
T might have stronger alignment requirements than
unsigned char.
Even so, the buffer being contiguous does not mean that
the whole object must be contiguous; only the so-called
"object representation" (standardese) must be contiguous.
> > Every
> > 'new' operator works with memory address returned to it by
> > the allocation function (3.7.3.1), placement new is not in
> > any way different, it just passes extra arguments to that
> > allocation function.
>
> The allocation function in this case returns the address
> it's given, and then an object is constructed at that
> address.
I believe it is possible to design a standard-conforming
implementation that involves a split object even with that
constraint.
> > It's the job of the allocation function
> > to recognise that the memory is split into pieces and not to
> > use it, I suppose.
>
> No, it's the job of the allocation function to return a
> pointer to memory suitable for construction of an object.
> The standard overload of ::operator new used by the
> regular form of placement new simply returns the "extra"
> argument it is given.
Consider the following implementation strategy. Base class
subobjects are allocated by constructors using a hidden
built-in allocator, and the main ("derivation") chunk of the
object just points to the base classes. sizeof(D) returns the
number of bytes occupied by the main chunk of D only
(including the pointers to base subobjects, but not including
the base subobjects themselves).
I believe that could be a correct C++ object model where the
value of an object is not contained within a contiguous chunk
of bytes.
Daveed
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: ron@sensor.com ("Ron Natalie")
Date: Fri, 11 Jul 2003 17:52:47 +0000 (UTC) Raw View
""Bo Persson"" <bop2@telia.com> wrote in message news:K3wPa.19934$dP1.37278@newsc.telia.net...
> No, the compiler can claim that unsigned char has the wrong alignment
> for a T and refuse.
Actually, it can even not refuse but blow up at runtime.
> If you use malloc(sizeof(T)) the returned block, if any, will be
> suitable.
new char[sizeof(T)] is requrired to behave the same way
>However malloc is specifically allowed to return a larger
> block than requested, to make it suitably aligned.
You mean it might allocate more memory...
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: v.Abazarov@attAbi.com ("Victor Bazarov")
Date: Sat, 12 Jul 2003 00:14:55 +0000 (UTC) Raw View
"Mirek Fidler" <cxl@volny.cz> wrote...
> > function return one chunk _always_. Again, I haven't seen any
> > explanation yet as to why _allowing_ to keep objects spread in
> > memory interferes with anything else.
>
> Perhaps I start to understand you. What you are claiming is that C++
> standard allows different layout for automatic/static objects and for
> objects on heap ? :)
Yes. For some reason some folks understand it in reverse.
Nothing says that when allocating an object using 'new' the
operation has to support construction of the object in non-
contiguous memory. Allocation function returns a memory
chunk, all contiguous, an everything is fine. However, if
I declare a local object or a global object, there is nothing
in the language that requires it to be in one piece. That's
how I read the Standard. That's how the language seems to
work. It doesn't contradict itself in that regard, I think.
It's not illogical to allow objects to be broken up. Only
POD objects have to have contiguous storage and that's the
requirement made explicitly. The fact that allocators need
contiguous storage and the fact that allocation functions
return contiguous storage for new objects to be constructed
in, doesn't change a thing...
Now, if I do
someNonPODClass object; // can it be broken up?
someNonPODClass *other = new (&object) someNonPODClass;
(which seems to be the argument against allowing breaking
even non-POD objects up), I have a slight problem. First,
the Standard does say that an object's lifetime ends as soon
as its _storage_is_reused_. However, in another paragraph
the Standard says that in order an object's lifetime ends
with execution of the destructor. To me it seems that due
to the 'execution of the destructor' requirement the code
above is ill-formed. Another argument towards allowing the
object in the code above to be broken up is that the used
"placement new" here does not necessarily create the object
directly in the storage of 'object'. It passes it onto the
allocation function, which could after detecting that the
storage is non-contiguous, return another, contiguous, piece
and ignore the non-contiguous one. If I were implementing
a compiler, that's what I'd do. OTOH, if it's possible to
create 'object' in a broken-up storage in the first place,
why can't we create another one, the "dynamic" object in
the same broken-up place? The layout will be the same, no?
That's just MHO, of course. I can be mistaken. It would
be nice to hear from others on the subject.
Victor
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: francis@robinton.demon.co.uk (Francis Glassborow)
Date: Sat, 12 Jul 2003 19:44:28 +0000 (UTC) Raw View
In article <vgtp84dh21hd21@corp.supernews.com>, Victor Bazarov
<v.Abazarov@attAbi.com> writes
>Yes. For some reason some folks understand it in reverse.
>Nothing says that when allocating an object using 'new' the
>operation has to support construction of the object in non-
>contiguous memory. Allocation function returns a memory
>chunk, all contiguous, an everything is fine. However, if
>I declare a local object or a global object, there is nothing
>in the language that requires it to be in one piece. That's
>how I read the Standard. That's how the language seems to
>work. It doesn't contradict itself in that regard, I think.
The new expression calls an allocator function operator new to get the
memory which the ctor uses to construct the object. One of these
allocator functions is the simple placement version. I do not understand
how the new expression is supposed to do other than assume that the
placement new returns a single contiguous chunk.
Now it is also allowed by the standard to explicitly call the dtor on an
object and then use the memory which the object had been occupying to
build another object of exactly the same type. There is consciously no
constraints on the origin of the object that was destroyed, the only
constraint is that if it was a stack object its memory must once again
contain an object of exactly the same type before it is automatically
destroyed when the name goes out of scope.
I am sorry if this is confused. But it is quite clear that even if some
perverted reading of the standard allows otherwise the only logical
mechanism is for all complete objects with the same dynamic type to have
the same layout. I have to say complete type because virtual bases and
MI introduce the necessity that some subobjects will be disjoint.
However I do not believe that it is allowed to try to destroy a base
subobject other than as part of the destruction of the complete object.
--
Francis Glassborow ACCU
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: ron@sensor.com ("Ron Natalie")
Date: Tue, 8 Jul 2003 15:04:00 +0000 (UTC) Raw View
""Bo Persson"" <bop2@telia.com> wrote in message news:sIbOa.15435$mU6.15382@newsb.telia.net...
> or storing smaller objects in the pad space between
> larger members.
Actually, there are restrictions on what it can do. Between
access specifiers, the subsequent non-static data members
must occupy increasing memory locations.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: cxl@volny.cz ("Mirek Fidler")
Date: Tue, 8 Jul 2003 18:27:18 +0000 (UTC) Raw View
> > How are new operators supposed to work then ? What does return
> > sizeof ? How are allocators supposed to work ?
>
> They are supposed to work anyway. The compiler writer will have to fix
> that!
>
> sizeof() reports the total size of the object.
Well, let us say that compiler indeed does something strange with
base classes, like storing them elsewhere and keeping pointer to them.
Then what is the sizeof of the object ? Size of last derived class,
or sum of all non-continuos chunks ?
Mirek
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: v.Abazarov@attAbi.com ("Victor Bazarov")
Date: Wed, 9 Jul 2003 02:43:26 +0000 (UTC) Raw View
"Mirek Fidler" <cxl@volny.cz> wrote...
> > > How are new operators supposed to work then ? What does return
> > > sizeof ? How are allocators supposed to work ?
> >
> > They are supposed to work anyway. The compiler writer will have to fix
> > that!
> >
> > sizeof() reports the total size of the object.
>
> Well, let us say that compiler indeed does something strange with
> base classes, like storing them elsewhere and keeping pointer to them.
>
> Then what is the sizeof of the object ? Size of last derived class,
> or sum of all non-continuos chunks ?
"The sizeof operator yields the number of bytes in the object
representation of its operand."
What does it matter whether the bytes are contiguous or spread around?
If you want to copy the object using memcpy or memmove you may only
do that with POD. Any other operation does not require the object to
be in contiguous memory, does it?
Victor
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: bo-staffan.lankinen@gbg.bonet.se ("Bo-Staffan Lankinen")
Date: Wed, 9 Jul 2003 18:41:01 +0000 (UTC) Raw View
> What does it matter whether the bytes are contiguous or spread around?
> If you want to copy the object using memcpy or memmove you may only
> do that with POD. Any other operation does not require the object to
> be in contiguous memory, does it?
I can matter when constructing with placement new.
Bo-Staffan
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: cxl@volny.cz ("Mirek Fidler")
Date: Wed, 9 Jul 2003 18:41:35 +0000 (UTC) Raw View
> > Then what is the sizeof of the object ? Size of last derived
class,
> > or sum of all non-continuos chunks ?
>
> "The sizeof operator yields the number of bytes in the object
> representation of its operand."
>
> What does it matter whether the bytes are contiguous or spread around?
> If you want to copy the object using memcpy or memmove you may only
> do that with POD. Any other operation does not require the object to
> be in contiguous memory, does it?
I thing operator new does. Custom allocators do too. That said, I
really do not understand how sizeof could return total number of bytes
of object representation, object would be splitted through the memory
and in the same time new would work while, at least, not wasting memory.
(See e.g. 5.3.4).
Mirek
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: francis@robinton.demon.co.uk (Francis Glassborow)
Date: Wed, 9 Jul 2003 21:56:12 +0000 (UTC) Raw View
In article <vgm79hgn64c2d6@corp.supernews.com>, Victor Bazarov
<v.Abazarov@attAbi.com> writes
>What does it matter whether the bytes are contiguous or spread around?
>If you want to copy the object using memcpy or memmove you may only
>do that with POD. Any other operation does not require the object to
>be in contiguous memory, does it?
Yes, just about all forms of placement new and overloading of new
require that the amount of memory to be allocated is known and
allocators (such as operator new) allocate contiguous memory.
--
Francis Glassborow ACCU
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: v.Abazarov@attAbi.com ("Victor Bazarov")
Date: Wed, 9 Jul 2003 22:02:43 +0000 (UTC) Raw View
"Bo-Staffan Lankinen" <bo-staffan.lankinen@gbg.bonet.se> wrote...
> > What does it matter whether the bytes are contiguous or spread around?
> > If you want to copy the object using memcpy or memmove you may only
> > do that with POD. Any other operation does not require the object to
> > be in contiguous memory, does it?
>
> I can matter when constructing with placement new.
I am not sure what you mean. How would that matter? Every
'new' operator works with memory address returned to it by
the allocation function (3.7.3.1), placement new is not in
any way different, it just passes extra arguments to that
allocation function. It's the job of the allocation function
to recognise that the memory is split into pieces and not to
use it, I suppose.
Victor
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: v.Abazarov@attAbi.com ("Victor Bazarov")
Date: Wed, 9 Jul 2003 22:03:03 +0000 (UTC) Raw View
"Mirek Fidler" <cxl@volny.cz> wrote...
> > > Then what is the sizeof of the object ? Size of last derived
> class,
> > > or sum of all non-continuos chunks ?
> >
> > "The sizeof operator yields the number of bytes in the object
> > representation of its operand."
> >
> > What does it matter whether the bytes are contiguous or spread around?
> > If you want to copy the object using memcpy or memmove you may only
> > do that with POD. Any other operation does not require the object to
> > be in contiguous memory, does it?
>
> I thing operator new does.
Operator new uses whatever the allocation function returns. If
the allocation function returns contiguous memory, so will be
the object.
> Custom allocators do too. That said, I
> really do not understand how sizeof could return total number of bytes
> of object representation, object would be splitted through the memory
> and in the same time new would work while, at least, not wasting memory.
> (See e.g. 5.3.4).
I can't see anything in 5.3.4 that would mandate 'new' not to
waste _any_ memory. AFAIK, many implementations actually "waste"
memory by keeping track of how the blocks were allocated and so
on.
Victor
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: hickin@cam.org ("John D. Hickin")
Date: Thu, 10 Jul 2003 03:53:34 +0000 (UTC) Raw View
----- Original Message -----
From: ""Mirek Fidler"" <cxl@volny.cz>
> I thing operator new does. Custom allocators do too. That said, I
> really do not understand how sizeof could return total number of bytes
> of object representation, object would be splitted through the memory
> and in the same time new would work while, at least, not wasting memory.
> (See e.g. 5.3.4).
>
But who says that it can't waste memory? It might have to be so...
If you can still get hold of the cfront compiler (or perhaps one having a
special mode that emulates cfront's idiosyncracies) you might see that an
inheritance in the form of a kite (i.e., _diamond of death_ with a pig tail)
actually has two instances of the virtual base; the generated code only
references (in consistent fashion) one of the virtual base class instances.
Certainly a waste of space, probably a bug, but it never really caused
problems.
I do think, however, that it was the intent of the standard to:
- stipulate that objects shall occupy contiguous storage
- all instances of a given type shall have the same size and layout
- aside from holes required because of alignment requirements, allow that
wasted space could be minimized
Regards, John.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: cxl@volny.cz ("Mirek Fidler")
Date: Thu, 10 Jul 2003 06:45:08 +0000 (UTC) Raw View
> > I thing operator new does.
>
> Operator new uses whatever the allocation function returns. If
> the allocation function returns contiguous memory, so will be
> the object.
Operator new can serve as interface between user defined allocation
function and storage occupied by object. AFAIK, standard requires new
implementor to return continuos block of memory. As long as you can
provide your own implementation of new, there seems to be some
problem....
> I can't see anything in 5.3.4 that would mandate 'new' not to
> waste _any_ memory. AFAIK, many implementations actually "waste"
> memory by keeping track of how the blocks were allocated and so
> on.
Yes, but they still return a continuous block of memory and standard
requires that requested size of this block will be sizeof(T).
Mirek
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: cxl@volny.cz ("Mirek Fidler")
Date: Thu, 10 Jul 2003 07:27:09 +0000 (UTC) Raw View
> I do think, however, that it was the intent of the standard to:
>
> - stipulate that objects shall occupy contiguous storage
> - all instances of a given type shall have the same size and layout
> - aside from holes required because of alignment requirements, allow
that
> wasted space could be minimized
I also do think there is no other possibility, anyway purpose of my
question was to sort out what information standard gives us about it and
whether there is a direct guarantee or if another interpretation is
possible.
Mirek
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: bo-staffan.lankinen@gbg.bonet.se ("Bo-Staffan Lankinen")
Date: Thu, 10 Jul 2003 07:27:08 +0000 (UTC) Raw View
> I am not sure what you mean. How would that matter? Every
> 'new' operator works with memory address returned to it by
> the allocation function (3.7.3.1), placement new is not in
> any way different, it just passes extra arguments to that
> allocation function. It's the job of the allocation function
> to recognise that the memory is split into pieces and not to
> use it, I suppose.
The placement new idiom is based on the object representation being one
contiguous memory-chunk. If the address of such a memory-chunk is passed to
a placement new expression and there are multiple invokations of the
placement new operator, different parts of the object will reside in the
same memory location because the placement new operator returns the address
of the memory-chunk for all the invokations.
Bo-Staffan
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: cxl@volny.cz ("Mirek Fidler")
Date: Fri, 4 Jul 2003 20:53:27 +0000 (UTC) Raw View
There is some indication that C++ implementation is allowed to store
base class suboject of derived class in different chunk of memory. Is
that true ? What paragraphs of standard deal with this issue ? (closest
I have found is 3.9/5, but it does not seems to be definitive).
If eventually it is (personally, I do not think so), how is e.g.
placement operator new expected to work ?
Mirek
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: v.Abazarov@attAbi.com ("Victor Bazarov")
Date: Sat, 5 Jul 2003 16:38:18 +0000 (UTC) Raw View
"Mirek Fidler" <cxl@volny.cz> wrote...
> There is some indication that C++ implementation is allowed to store
> base class suboject of derived class in different chunk of memory. Is
> that true ? What paragraphs of standard deal with this issue ? (closest
> I have found is 3.9/5, but it does not seems to be definitive).
>
> If eventually it is (personally, I do not think so), how is e.g.
> placement operator new expected to work ?
1.8/5 only requires that a POD object occupies contiguous bytes of
storage. To me that says that a non-POD object can be split into
parts scattered around the program's memory.
Victor
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: cxl@volny.cz ("Mirek Fidler")
Date: Mon, 7 Jul 2003 01:13:54 +0000 (UTC) Raw View
> > There is some indication that C++ implementation is allowed to store
> > base class suboject of derived class in different chunk of memory.
Is
> > that true ? What paragraphs of standard deal with this issue ?
(closest
> > I have found is 3.9/5, but it does not seems to be definitive).
> >
> > If eventually it is (personally, I do not think so), how is e.g.
> > placement operator new expected to work ?
>
> 1.8/5 only requires that a POD object occupies contiguous bytes of
> storage. To me that says that a non-POD object can be split into
> parts scattered around the program's memory.
How are new operators supposed to work then ? What does return
sizeof ? How are allocators supposed to work ?
Mirek
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: bop2@telia.com ("Bo Persson")
Date: Tue, 8 Jul 2003 01:36:00 +0000 (UTC) Raw View
""Mirek Fidler"" <cxl@volny.cz> skrev i meddelandet
news:be75da$20irt$1@ID-198693.news.dfncis.de...
> > > There is some indication that C++ implementation is allowed to
store
> > > base class suboject of derived class in different chunk of
memory.
> Is
> > > that true ? What paragraphs of standard deal with this issue ?
> (closest
> > > I have found is 3.9/5, but it does not seems to be definitive).
> > >
> > > If eventually it is (personally, I do not think so), how is e.g.
> > > placement operator new expected to work ?
> >
> > 1.8/5 only requires that a POD object occupies contiguous bytes of
> > storage. To me that says that a non-POD object can be split into
> > parts scattered around the program's memory.
No, not really. It says that PODs are required to store its members in
the order they are declared, just like in a C struct.
For non-POD objects, the compiler is allowed to optimize the storage
any way it wants, like storing public data at one end and private data
at the other, or storing smaller objects in the pad space between
larger members. Multiple base classes will be stored somehow, but it
is mostly up to the implementation.
>
> How are new operators supposed to work then ? What does return
> sizeof ? How are allocators supposed to work ?
They are supposed to work anyway. The compiler writer will have to fix
that!
sizeof() reports the total size of the object. How it does that is not
specified. Storing all the data in one piece would be an obvous
solution. :-)
Bo Persson
bop2@telia.com
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]