Re: Is the 'as if' rule appliable here? (A reawakening)
On Apr 4, 1:23 am, "Daniel Kr?gler" <daniel.krueg...@googlemail.com>
wrote:
James Kanze schrieb:
C++98 said that the implementation used "string"; I don't think
you can detect if it doesn't, so as-if covers it.
Good point, I have overlooked this subtle difference!
And as I see in that moment, even the 14882:2003
document uses the notion of "string".
The current draft says that the implementation used
basic_string< charT, traits >, which means that it uses
a traits class which I wrote; that might provide a means.
Do you mean that it provides means to detect a
difference?
Probably not, but maybe. Some code which you wrote is involved,
so potentially, you at least have a chance. But the standard
doesn't specify exactly how many calls to which traits functions
will occur for which basic_string operations, nor which
operations are actually used in the function in question, and of
course, there's nothing to prevent an implementation from using
the traits class above without using basic_string, either.
One possibility might be to specialize basic_string on a type
you defined, and instrument the specialization. The standard
says (?17.4.3.1): "A program may explicitly instantiate any
templates in the standard library only if the declaration
depends on the name of a user-defined type of external linkage
and the instantiation meets the standard library requirements
for the original template." I'm not sure just how much leeway
that gives. Suppose your specialization of basic_string behaved
exactly like basic_string, except that you counted the numer of
times a constructor was invoked, and made that information
available. That would definitly result in an observable
difference if the implementation never used basic_string, but
I'm not sure that that still qualifies as "meets the standard
library requirements for the original template."
Note that this change (between C++98 and the current draft)
could also conceivably break code. Again, however, it would
require a really perverse traits class, and I'll bet that in
practice, no real code is affected.
That is true, although I always have accepted such breaks,
if these where due to defect reports. OK, one reasonable
argument against such a break is, that it would *not* break
an already defective code in this case.
From my view-point a well-written replacement using e.g.
a C array of fixed length would be sufficient to provide this
guarantee. The tricky point might be the situation of too
little free store,
You don't need any free store, since you can allocate on stack:
charT buffer[ N ] ;
Yes, of course. My reasoning was vice-versa: If I replace
an earlier (basic_)string-based implementation by one
which uses a stack-based buffer, this is (theoretically)
detectable via the memory allocator. And in situations of
too little memory the older impl. would have thrown, the
new one maybe not.
Except that you have no guarantees as to when the allocator may
be called. Suppose the library's implementation of basic_string
uses the small string optimization, with "small" being defined
as anything less that 100 KB. Suppose the standard allocator
gets memory in very big blocks, and only rarely goes to your
instrumented global allocator. Suppose on the other hand that
the implementation uses vector< charT >, instead of
basic_string< charT >? I don't think you can use the allocator
as an observable external behavior here.
Yes, these are pure lawyer thoughts,
but I try to position myself in an implementor, that
tries to guess it's chances of probably crazy code
breaks. This may sound silly (and most users would
probably applaud the new code), but I read once, that
during at least one MS Window's version change the
MS crew provided special handlers for some selected
games to work on the newer version, although the
reason of failing to do so (in the newer version) were
based on programming errors in the game. These were
programming errors's which the old OS version accepted
w/o any OS exception, but were already defective in
the old version..
All major vendors do that. Proving to your customer that he
doesn't know what he is doing is not a particularly effective
way of increasing sales.
[..]
that every expression involving new/delete (in which hidden
way ever) *must* necessarily have observable side-effects
and that this means that we cannot replace them by
alternative options?
That's the way I've always interpreted it. Particularly in that
the standard, in some cases, takes pains to decouple the two,
e.g. ?20.6.1.1/6 "the storage is obtained by calling ::operator
new(std::size_t), but it is unspecified when or how often this
function is called." If an implementation had the right,
generally, to skip dynamic allocation, then this sentence
wouldn't be necessary.
Hmmh, I have understood this from the view-point of a user of
allocator. If I use the allocator::allocate function, I
explicitely *demand* this call and I'm willing to accept the
consequences. The additional information is provided, because
I might also provide ::operator new(std::size_t), in the
example you gave, and I could consider to write disgustedly
e-mails to my compiler vendor just because not every
invokation of allocate did also invoke my ::operator new.
After that I get a answer in a friendly tone, which nicely
explains me that this behaviour is granted by the standard and
that I should be happy to have such a high-quality allocator
implementation, which uses a very intelligent and an
internationally patented block allocator... This way or the
other, the system *will* aquire free store from the OS via
*my* operator new, but I don't know exactly when.
But you are right: If I don't know, exactly *when* my
allocator is invoked, it will usually not be an easy task
for me to detect a given string instantiation. But, if
I also have the allocator in my hands... ;-)
You don't. The default allocator is part of the standard
library, and specification for the operator says that it uses
basic_string<charT, traits> (and thus, the default allocator).
For the moment, I'd like to see a conforming program which could
tell.
If *you* say that, I'm convinced - no kidding.
I've not tried. I'm not sure how to go about it, but I've also
seen no proof that it isn't possible.
A lot depends, too, on just how much latitude we do have in
implementing a traits class or a specialization of basic_string.
I'm not sure that the standard is really clear about this.
Exceeding resource limitations is undefined behavior. (I forget
where it says this in the standard, but someone showed it to me
once.)
If you find it again - please write me an e-mail! (The address
is usable)
?1.4 Implementation compliance
[...]
-- If a program contains no violations of the rules in this
International Standard, a conforming implementation
shall, WITHIN ITS RESOURCE LIMITS, accept and correctly
execute that program.
Since the standard never says what the implementation should do
if the resource limits are exceeded, it's undefined behavior.
One obvious reason for this is that the standard doesn't want to
define behavior for cases like stack overflow.
Note that there are specific exceptions as well. The standard
does specify what happens if there is insufficient memory to
serve an operator new request, for example, so that is not
undefined behavior. In theory, at least. In practice, the
implementation will never try to do better than the OS, and if
the OS uses lazy page allocation (e.g. Linux, in its default
configuration), you will effectively get undefined behavior,
even if the standard says its not. And of course, the standard
makes no guarantees about time, so if the OS suspends your
process when it can't fulfill a memory request, and only resumes
it when the memory is available (like Windows, at least in some
configurations), it's fully conformant... and fully useless if
you're trying to create any sort of reliable system.
--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orient?e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S?mard, 78210 St.-Cyr-l'?cole, France, +33 (0)1 30 23 00 34
---
[ 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.comeaucomputing.com/csc/faq.html ]