www.digitalmars.com         C & C++   DMDScript  

c++.stlsoft - fixed_array, at, and NDEBUG

reply Neal Becker <ndbecker2 gmail.com> writes:
I believe that, contrary to the documentation, that 'at' uses assert, and
that assert is disabled if NDEBUG is defined.  So, if NDEBUG is defined,
then 'at' won't actually perform checking.  Note: I'm not complaining.  The
current behavior is what I want.  I just think the documentation should be
clarified.
Mar 20 2007
parent reply Matthew Wilson <no-one nowhere.no.com> writes:
Neal Becker Wrote:

 I believe that, contrary to the documentation, that 'at' uses assert, and
 that assert is disabled if NDEBUG is defined.  So, if NDEBUG is defined,
 then 'at' won't actually perform checking.  Note: I'm not complaining.  The
 current behavior is what I want.  I just think the documentation should be
 clarified.
AFAIK, the at() overloads only use assert in builds when exceptions are not supported. When exception-support is on, they throw std::out_of_range. Can you give me some context for your observations, so I can get a hold on what precisely you're referring to? Thanks Matthew
Apr 06 2007
parent reply Neal Becker <ndbecker2 gmail.com> writes:
Matthew Wilson wrote:

 Neal Becker Wrote:
 
 I believe that, contrary to the documentation, that 'at' uses assert, and
 that assert is disabled if NDEBUG is defined.  So, if NDEBUG is defined,
 then 'at' won't actually perform checking.  Note: I'm not complaining. 
 The
 current behavior is what I want.  I just think the documentation should
 be clarified.
AFAIK, the at() overloads only use assert in builds when exceptions are not supported. When exception-support is on, they throw std::out_of_range. Can you give me some context for your observations, so I can get a hold on what precisely you're referring to?
I'm testing on linux (fedora fc6 x86_64) with: gcc version 4.1.1 20070105 (Red Hat 4.1.1-51) stlsoft-1.9.1.beta46 and as shown by gdb, it _is_ calling assert, not using exceptions. Do I need to configure something?
Apr 11 2007
parent reply "Matthew Wilson" <matthew hat.stlsoft.dot.org> writes:
"Neal Becker" <ndbecker2 gmail.com> wrote in message
news:evj5cu$1rj5$1 digitalmars.com...
 Matthew Wilson wrote:

 Neal Becker Wrote:

 I believe that, contrary to the documentation, that 'at' uses assert,
and
 that assert is disabled if NDEBUG is defined.  So, if NDEBUG is
defined,
 then 'at' won't actually perform checking.  Note: I'm not complaining.
 The
 current behavior is what I want.  I just think the documentation should
 be clarified.
AFAIK, the at() overloads only use assert in builds when exceptions are not supported. When exception-support is on, they throw
std::out_of_range.
 Can you give me some context for your observations, so I can get a hold
on
 what precisely you're referring to?
I'm testing on linux (fedora fc6 x86_64) with: gcc version 4.1.1 20070105 (Red Hat 4.1.1-51) stlsoft-1.9.1.beta46 and as shown by gdb, it _is_ calling assert, not using exceptions. Do I need to configure something?
This is all very odd. I've just knocked this up and tested on Windows with both VC++8 and GCC3.4, and on Mac OSX with GCC 4.0. In all cases, I tested a debug variant (-D_DEBUG -DDEBUG -UNDEBUG) and a released variant (-U_DEBUG -UDEBUG -DNDEBUG), and it all works just fine, i.e. an instance of std::out_of_range is thrown and no assertions are fired. Yours, confused Matthew begin 666 fixed_array_test3.zip M3.BUU[OGN>.Y!OX[X_6P:RB42 ]*M/JC%EP3QJE4'RT[T*8B4I+C?+W=+ ,_ M> `PH;2D9+,,1BP-/=1TJVWR7K &-%4ZNK 7Q0-G]=F4C.LE8$FE)T!D`HK] M3\LC6D/G81?>'KZP SG1D2ENJF(YESFNM\=+[XRK)KI>1S:&H4JTE21\12?Q ME7;<)NXST<YLSEOX#XD3C G^BF%%<2QD %OBC>99$\?'FP'C-HQ_"!L<:W13 M\/4\/"*C/ 'S700X02MD=)T""I4N<"N-7 W;4*ZPES2*80K9`J93=NM_!.P< M5.\D1]Z+/G]02P$"% `4````" !D4XPV*Y*/-FH!```*`P``%0`````````! '`)T!```````` ` end
Apr 11 2007
parent reply Neal Becker <ndbecker2 gmail.com> writes:
Matthew Wilson wrote:

 
 "Neal Becker" <ndbecker2 gmail.com> wrote in message
 news:evj5cu$1rj5$1 digitalmars.com...
 Matthew Wilson wrote:

 Neal Becker Wrote:

 I believe that, contrary to the documentation, that 'at' uses assert,
and
 that assert is disabled if NDEBUG is defined.  So, if NDEBUG is
defined,
 then 'at' won't actually perform checking.  Note: I'm not complaining.
 The
 current behavior is what I want.  I just think the documentation
 should be clarified.
AFAIK, the at() overloads only use assert in builds when exceptions are not supported. When exception-support is on, they throw
std::out_of_range.
 Can you give me some context for your observations, so I can get a hold
on
 what precisely you're referring to?
I'm testing on linux (fedora fc6 x86_64) with: gcc version 4.1.1 20070105 (Red Hat 4.1.1-51) stlsoft-1.9.1.beta46 and as shown by gdb, it _is_ calling assert, not using exceptions. Do I need to configure something?
This is all very odd. I've just knocked this up and tested on Windows with both VC++8 and GCC3.4, and on Mac OSX with GCC 4.0. In all cases, I tested a debug variant (-D_DEBUG -DDEBUG -UNDEBUG) and a released variant (-U_DEBUG -UDEBUG -DNDEBUG), and it all works just fine, i.e. an instance of std::out_of_range is thrown and no assertions are fired. Yours, confused
assert is called from here: STLSOFT_MESSAGE_ASSERT("fixed array index out of range", i0 < m_d0); stlsoft::do_construction<int>, true>::operator[] ( this=0x7fff01935f70, i0=11) at /usr/local/src/stlsoft/include/stlsoft/containers/fixed_array.hpp:962 Are you saying that "STLSOFT_MESSAGE_ASSERT" should expand to throw rather than assert? It's hard to tell - twisty maze of macros (all different)
Apr 12 2007
next sibling parent Neal Becker <ndbecker2 gmail.com> writes:
It seems there are both STLSOFT_MESSAGE_ASSERT and STLSOFT_THROW_X used in
fixed_array.  Did you really want that?  Shouldn't this be using one or the
other consistently?

It seems that range_check uses throw.  at uses range_check.

at_unchecked uses assert?!!?  I'm really surprised by this.  I thought
unchecked meant, uh, unchecked??
Apr 12 2007
prev sibling parent reply "Matthew Wilson" <matthew hat.stlsoft.dot.org> writes:
"Neal Becker" <ndbecker2 gmail.com> wrote in message
news:evl4s6$2ffu$1 digitalmars.com...
 Matthew Wilson wrote:

 "Neal Becker" <ndbecker2 gmail.com> wrote in message
 news:evj5cu$1rj5$1 digitalmars.com...
 Matthew Wilson wrote:

 Neal Becker Wrote:

 I believe that, contrary to the documentation, that 'at' uses
assert,
 and
 that assert is disabled if NDEBUG is defined.  So, if NDEBUG is
defined,
 then 'at' won't actually perform checking.  Note: I'm not
complaining.
 The
 current behavior is what I want.  I just think the documentation
 should be clarified.
AFAIK, the at() overloads only use assert in builds when exceptions
are
 not supported. When exception-support is on, they throw
std::out_of_range.
 Can you give me some context for your observations, so I can get a
hold
 on
 what precisely you're referring to?
I'm testing on linux (fedora fc6 x86_64) with: gcc version 4.1.1 20070105 (Red Hat 4.1.1-51) stlsoft-1.9.1.beta46 and as shown by gdb, it _is_ calling assert, not using exceptions. Do
I
 need to configure something?
This is all very odd. I've just knocked this up and tested on Windows with both VC++8 and GCC3.4, and on Mac OSX with GCC 4.0. In all cases, I tested a debug variant (-D_DEBUG -DDEBUG -UNDEBUG) and a released variant (-U_DEBUG -UDEBUG -DNDEBUG), and it all works just
fine,
 i.e. an instance of std::out_of_range is thrown and no assertions are
 fired.

 Yours, confused
assert is called from here: STLSOFT_MESSAGE_ASSERT("fixed array index out of range", i0 < m_d0);
std::allocator<int>, stlsoft::do_construction<int>, true>::operator[] (
     this=0x7fff01935f70, i0=11) at
/usr/local/src/stlsoft/include/stlsoft/containers/fixed_array.hpp:962 Ok, now I'm even more confused. Well, non-technically, anyway. I thought we were talking about at(). Probably my bad. ;-/ Certainly the subscript operator uses an assert ... as does at_unchecked().
 Are you saying that "STLSOFT_MESSAGE_ASSERT" should expand to throw rather
than assert? No. Not at all. It comes down to the contracts of the various methods. (Please excuse me if I'm telling you stuff you already know in the following <g>) The contract for the subscript operator(s) is: Precondition: index < size() Postcondition: return of a reference (mutating or non-mutating) to the element referred to by the index It's exactly the same for at_unchecked() (and the newly added function call operators(), in beta 48, just released), except that for _2d and above there are multiple indexes. The contract for at() is very different: Precondition: Postcondition: return of a reference to the element referred to by the index if index < size(). Throw an exception of std::out_of_range if index >= size() Since it's the responsibility of the caller to fulfil the precondition, it means that use of subscript operator/at_unchecked/function call operator must be passed an index in the range [0, size()). If not, the contract is broken, the program is not well-formed. With at(), the caller can provide *any* value for index, and the precondition (which is empty) is satisfied, and the program is still well-formed. So, the only remaining question in this (as in any contract programming) is to decide what, if any, enforcement of the contract is made. It's important to remember that just because a contract is not, or may not be, enforced in code, it still applies. (Enforcement comprises Detection, Reporting and Response. Usually, in the guise of an assert(), this comprises a conditional test, an fprintf() to stderr, and invocation of exit().) The question then comes down to what enforcement, if any, is employed. I tend to adopt the common approach of use of assertions, which means that in debug builds the enforcement is on, and in release builds enforcement is off. Naturally, this relies on the (sometimes erroneous) assumption that all code paths will be exercised in debug-mode testing. To account for this not being so, I allow, via customisation of the STLSoft asserts, for users to keep enforcement on in all builds. That's their choice. (When building long lasting and complex systems, e.g. network servers, I usually keep some/all of the enforcements on in production, though usually just the ones in application code, rather than the low-level stuff in classes such as the fixed arrays. That way, operation outside the design of the software can be detected and reported early, and the response is to kill the process immediately, before it can do, theoretically, anything at all, which would usually be bad. <g>) Anyway, the main points are: (i) the difference between the strict contract for the at_unchecked()/op []/op () and the loose contract for at(), and (ii) that whether or not the strict contract is enforced, it still applies. So, I think we probably are misunderstanding each other in interpreting the behaviour. As far as I've been able to determine, the software behaves in accordance with my original intent: at() checks and throws, whereas at_unchecked()/op []/op () assert on contract violations in debug builds and do no checking at all in release builds. Does this square with your observations? If so, all is well. If not, I need to fix something. HTH Matthew
Apr 12 2007
next sibling parent "Matthew Wilson" <matthew hat.stlsoft.dot.org> writes:
 The contract for the subscript operator(s) is:
     Precondition: index < size()
     Postcondition: return of a reference (mutating or non-mutating) to the
 element referred to by the index
<snip>
 The contract for at() is very different:
     Precondition:
     Postcondition: return of a reference  to the element referred to by
the
 index if index < size(). Throw an exception of std::out_of_range if index
=
 size()
<snip>
 Anyway, the main points are: (i) the difference between the strict
contract
 for the at_unchecked()/op []/op () and the loose contract for at(), and
(ii)
 that whether or not the strict contract is enforced, it still applies.


 So, I think we probably are misunderstanding each other in interpreting
the
 behaviour. As far as I've been able to determine, the software behaves in
 accordance with my original intent: at() checks and throws, whereas
 at_unchecked()/op []/op () assert on contract violations in debug builds
and
 do no checking at all in release builds.

 Does this square with your observations? If so, all is well. If not, I
need
 to fix something.
Sorry, one last thing to add. When compiling without exception support, the contract for at() becomes the same as that of op []/op ()/at_unchecked. Hmmm. Having said that, now I'm thinking that it may be better to simply remove at when !defined(STLSOFT_CF_EXCEPTION_SUPPORT). Anyway, that doesn't affect any of the main argument in the previous post. Matthew
Apr 12 2007
prev sibling parent reply Neal Becker <ndbecker2 gmail.com> writes:
Matthew Wilson wrote:

[...]

 
 So, I think we probably are misunderstanding each other in interpreting
 the behaviour. As far as I've been able to determine, the software behaves
 in accordance with my original intent: at() checks and throws, whereas
 at_unchecked()/op []/op () assert on contract violations in debug builds
 and do no checking at all in release builds.
 
 Does this square with your observations? If so, all is well. If not, I
 need to fix something.
 
Thanks so much for the excellent explanation. Yes, the current behavior is just what I want. I do still find it a little odd that one path uses assert and the other throw. Not that it really matters.
Apr 12 2007
parent reply "Matthew Wilson" <matthew hat.stlsoft.dot.org> writes:
"Neal Becker" <ndbecker2 gmail.com> wrote in message
news:evlv3h$oa6$1 digitalmars.com...
 Matthew Wilson wrote:

 [...]

 So, I think we probably are misunderstanding each other in interpreting
 the behaviour. As far as I've been able to determine, the software
behaves
 in accordance with my original intent: at() checks and throws, whereas
 at_unchecked()/op []/op () assert on contract violations in debug builds
 and do no checking at all in release builds.

 Does this square with your observations? If so, all is well. If not, I
 need to fix something.
Thanks so much for the excellent explanation. Yes, the current behavior
is
 just what I want.
Cool. So, have you been using the function call operators, as per your request, from beta 48? Work fine? :-)
Apr 12 2007
parent reply Neal Becker <ndbecker2 gmail.com> writes:
Matthew Wilson wrote:

[...]
 So, have you been using the function call operators, as per your request,
 from beta 48? Work fine? :-)
AFAICT, it works fine. I would suggest to implement operator()() in terms of at_unchecked, DRY, but it's your code :)
Apr 13 2007
parent reply "Matthew Wilson" <matthew hat.stlsoft.dot.org> writes:
"Neal Becker" <ndbecker2 gmail.com> wrote in message
news:evo22q$1o58$1 digitalmars.com...
 Matthew Wilson wrote:

 [...]
 So, have you been using the function call operators, as per your
request,
 from beta 48? Work fine? :-)
AFAICT, it works fine. I would suggest to implement operator()() in terms of at_unchecked, DRY, but it's your code :)
Ah yes. Doh! The perils of using temporary macros in one's IDE. ;-) I'll fix it up.
Apr 13 2007
parent "Matthew Wilson" <matthew hat.stlsoft.dot.org> writes:
"Matthew Wilson" <matthew hat.stlsoft.dot.org> wrote in message
news:evon5o$1k8r$1 digitalmars.com...
 "Neal Becker" <ndbecker2 gmail.com> wrote in message
 news:evo22q$1o58$1 digitalmars.com...
 Matthew Wilson wrote:

 [...]
 So, have you been using the function call operators, as per your
request,
 from beta 48? Work fine? :-)
AFAICT, it works fine. I would suggest to implement operator()() in
terms
 of at_unchecked, DRY, but it's your code :)
Ah yes. Doh! The perils of using temporary macros in one's IDE. ;-) I'll fix it up.
Done. (And I've enhanced the unit-tests from their previous parlous coverage <g>) Thanks for the keen-eye and sharp brain!
Apr 13 2007