Topic: Safety critical applications, was problems with locale and its facets


Author: Valentin Bonnard <bonnardv@pratique.fr>
Date: 1998/06/23
Raw View
J. Kanze <kanze@gabi-soft.fr> writes:

> Out of context: as a simple rule, safety-critical
> systems must be 100% deterministic, and must be provably so.

I like program proofs. Let's discuss that vs language design.

> IMHO, this rules out dynamic memory allocation

Except if you could recover from a failure to allocate (unlikely).

> all indirection in program flow paths (e.g. virtual functions)

Virtual functions are sometimes used to patch a class; That's
why some people say that functions should be virtual by
default. I don't do that and I only use virtual functions in
well specified ways.

That is, I make a function virtual for a reason, I document it
and say what the overrider can/can't do.

I think that if you ban good uses of virtual functions, you should
also ban functions. Calling a function is like pluging its semantics
in the called semantics; overiding a virtual function is the same
kind of thing.

I don't know any (formal) semantic of virtual functions, but
I am sure anyone can write one easilly.

> and anything that violates the principle of
> single-entry/single-exit.

Let me desagree. You can do checked formal proofs on programs
using only goto; there is a semantic for that (is it called the
label semantic ?).

(Not that I want to encourage the use of goto !)

I understand that unstructured code doesn't make sens with a
notationnal semantic, but what about the denotationnal
semantic ? It seems ok (to me).

The problem with C is that it's an ugly language; I haven't
seen a formal semantic for it (anyone ?). EC++ doesn't do
anything to remove the uglyness, and doesn't make it anymore
formalisable/provable.

--

Valentin Bonnard                mailto:bonnardv@pratique.fr
info about C++/a propos du C++: http://pages.pratique.fr/~bonnardv/


[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: jkanze@otelo.ibmmail.com
Date: 1998/06/24
Raw View
In article <01bd9e66$95e3f7c0$049485cc@gcolvin-hpc>,
  "Greg Colvin" <spam@me.not> wrote:
>
> J. Kanze <kanze@gabi-soft.fr> wrote in article
<m3d8c1ywqn.fsf_-_@gabi-soft.fr>...
> > Mike Davies <mike_davies@noco.demon.co.uk> writes:
> > |>  >In this case, you are simply wrong.  In hi-rel code, exceptions are
> > |>  >generally banned, because proving exception safety is too difficult.
>
> More precisely, I think, because the mathematics currently used for
> reasoning about critical systems doesn't take exceptions into account.

Exact.  That is basically what I was trying to say.

I don't believe that such reasoning is impossible, but at present, the
necessary mathematics has either not been developped, or is not widely
known.

> > |>  No, I don't agree. It is completely trivial to make C++ code exception
> > |>  safe : compile all modules with exceptions enabled and use the
exception
> > |>  enabled version of the library. Then wrap the contents of main() in a
> > |>  try...catch block.
>
> It's possible, but not that easy.  For example, if the destructor of a
> container element throws an exception you get undefined behavior.
>
> > See any number of back issues of C++ Reports; there was a number of
> > articles concerning exception safety in them about a year or so ago.  In
> > one of them (the first?), Tom Cargill "proved" it impossible to write a
> > Stack class that was exception safe.
>
> Tom proved only that a stack whose pop operation returns a reference to
> the popped value cannot be safe.  The standard stack is safe.  The other
> articles have mostly been outdated by progress in the standard, prompted
> in part by those articles.

I wasn't really thinking of the standard stack class, but of Stack as
an example (the example Tom used) of an apparently simple class becoming
impossibly difficult when exception safety is taken into account.

Whether the standard stack is safe or not depends on the implementation--
the standard requires a certain degree of safety (enough for all practical
uses, IMHO), but implementations have been known to contain errors.

Again: the argument isn't whether you can write robust code in the face
of exceptions, but whether you can actually mathematically prove the
code to be robust, with enough confidence to use it in safety-critical
applications.

--
James Kanze    +33 (0)1 39 23 84 71    mailto: kanze@gabi-soft.fr
        +49 (0)69 66 45 33 10    mailto: jkanze@otelo.ibmmail.com
GABI Software, 22 rue Jacques-Lemercier, 78000 Versailles, France
Conseils en informatique orient   e objet --
              -- Beratung in objektorientierter Datenverarbeitung

-----== Posted via Deja News, The Leader in Internet Discussion ==-----
http://www.dejanews.com/   Now offering spam-free web-based newsreading
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: kanze@gabi-soft.fr (J. Kanze)
Date: 1998/06/22
Raw View
Mike Davies <mike_davies@noco.demon.co.uk> writes:

|>  In article <6lj95e$bt6$1@nnrp1.dejanews.com>, jkanze@otelo.ibmmail.com
|>  writes
|>  >>
|>  >> It is not correct to say that new and delete are "completely out of the
|>  >> question" for safety critical code. There are features in C++ that allow
|>  >> you to have deterministic dynamic de/allocation. Of course you have to
|>  >> do the work.
|>  >
|>  >These features are also in EC++.  However, the effort of proving the
|>  >deterministic characteristics of the allocation are often superior to
|>  >the effort necessary to not use new and delete.
|>
|>  I agree of course that you should use whichever technique is best suited
|>  to the task at hand. You said however that new and delete are
|>  "completely out of the question" for safety critical systems and were
|>  using this to support your argument that embedded systems will not miss
|>  certain features of C++, or am I mistaken ?

My point is not to argue for or against EC++; I more or less favor it,
as long as it is understood that it has only limited applicability, and
should not be used as an excuse to not do better when you can.

I'm no longer sure what comment triggered my remark, so it's hard to put
it in context.  Out of context: as a simple rule, safety-critical
systems must be 100% deterministic, and must be provably so.  IMHO, this
rules out dynamic memory allocation (not because it isn't possible, but
because it is significantly more expensive in terms of implementation
effort than the alternatives), all indirection in program flow paths
(e.g. virtual functions) and anything that violates the principle of
single-entry/single-exit.

I would like to stress that such draconian restrictions are only
applicable to safety-critical applications, where the cost of a program
failure is unacceptable, period.  Most applications NEED dynamic memory,
in order to avoid fixed limits.  Most moderately large applications need
virtual functions, inheritance, and IMHO, multiple inheritance.  And I'm
willing to admit that exceptions also have a role to play, despite the
many articles against them by people better versed in the subjet than I
am.

I also don't know what this has to do with EC++, or how we got on to
this argument to begin with.  (Which doesn't mean that I don't think the
point important -- safety critical applications have other constraints
than normal code.)

|>  >> One of the main arguments for using a feature provided as part of a
|>  >> language rather than implementing it yourself is that the resulting code
|>  >> is more likely to be correct.
|>  >
|>  >I guess it depends.  My experience in embedded systems with C++ is that
|>  >compiler errors outnumber errors in my code by a ration of 2 to 1.  (This
|>  >was with earlier compilers -- I doubt I find this the case with any of
|>  >the compilers I now use.)
|>
|>  I don't know which C++ compilers you have used but I am astonished to
|>  hear this. I have used the Borland and Watcom compilers and although
|>  there has not been a spec for the language 'till now I could number the
|>  bugs I've run into in either of these compilers on the fingers of one
|>  hand. I only wish that were true of my code :-) (during the development
|>  process anyway). The situation with libraries may be slightly worse
|>  though.

I can only remember one case where there were more than five errors in
the compiler myself.  But that seems like a lot to me.  I've tried to
maintain statistics on my own work over the years, and I find on an
average 1 error per 10000 lines of code.  This is measured after
compilation and link, but before any testing -- errors detected by the
compiler or linker are NOT included.  And that includes ALL code --
obviously, safety critical code is more carefully reviewed.  And the
safety critical part is typically less than 10000 lines of code.

|>  >One of the main reasons for the high number of compiler errors was that
|>  >the language was continuously evolving, so each compiler update, while
|>  >correcting some errors, introduced others.
|>  >
|>  >> Are you saying for instance that a language
|>  >> without exception handling can be used to write more rugged code in a
|>  >> given timescale than one with that facility ? I disagree.
|>  >
|>  >In this case, you are simply wrong.  In hi-rel code, exceptions are
|>  >generally banned, because proving exception safety is too difficult.
|>
|>  No, I don't agree. It is completely trivial to make C++ code exception
|>  safe : compile all modules with exceptions enabled and use the exception
|>  enabled version of the library. Then wrap the contents of main() in a
|>  try...catch block.

See any number of back issues of C++ Reports; there was a number of
articles concerning exception safety in them about a year or so ago.  In
one of them (the first?), Tom Cargill "proved" it impossible to write a
Stack class that was exception safe.

|>  Of course you then have the problem of what to do when you do catch an
|>  error, but this is an easier problem than the problem of finding a
|>  function that returns an error code that the calling code just
|>  *silently* ignores. I know which bug I'd find easier to uncover if I was
|>  a SW Test Engineer :-)

I know that if I leave either problem to the test engineers, I've failed
in my job.  I know that this is a problem that code review typically
checks.  I know that at least one application I've worked on used a
ReturnCode class that aborted if the destructor was called before the
status was read.

I also know that just catching an exception somewhere, with no concern
as to what happens between the throw point and the catch point, only
works if the code has been carefully designed for it to work.  (Nothing
really surprising about this.  Has anyone ever seen code that worked
without being carefully designed to work?)

|>  ...snip...
|>
|>  >
|>  >> Its is all very well saying that a compiler for a complicated language
|>  >> is likely to have more defects than a compiler for a simple one.  This
|>  >> is likely true, the problem is that application code will contain *far*
|>  >> more defects than either of the compilers (it simply isn't thrashed to
|>  >> the same extent for one thing).
|>  >
|>  >See above.  This hasn't been my experience in the past (when I worked on
|>  >such systems).  In general, I doubt that it is the case for hi-rel
|>  >systems -- for such systems, the code is extensively verified and tested,
|>  >much more than a compiler typically is.  And having thousands of people
|>  >throwing random code at a compiler is NOT thorough testing.
|>
|>  It's fair to say that one reason C++ hasn't been used in (eg) Aerospace
|>  applications is the lack of a standard against which to test it. I don't
|>  think that this is a reason in itself to cut the standard for C++ down
|>  when we have one.

These are two points I think we can totally agree on.  One of the
biggest problems I've had with C++ has been the lack of a standard -- my
major applications field (telecoms) isn't quite as safety-critical as
Aerospace, but Deutsche Telecom tend to be quite unhappy if the main
truck line between Frankfurt and Berlin goes done.  Unhappy enough to
write penalties into the contract if it does.

I've also written what I consider real safety critical systems: a
locomotive break system, for example.  In that case, I didn't use C++: I
only had 8 KByte of PROM, and C++ was still just an experiment in Bell
Labs called C with Classes at the time.  Today, I suspect that I might
have 64KBytes or more of PROM, but I still think that I'd use Ada, or
failing that C, rather than C++.  EC++ *might* be an alternative.

|>  It is still the case that an application relying on a correctly
|>  implemented language feature will have a better chance of being bug-free
|>  than one where the programmer has had to implement the feature
|>  themselves. Otherwise surely the only language choice for safety
|>  critical systems would be assembler ?   :-)

There are two aspects to consider.  The first is "correctly implemented
language features."  Judging from the discussions I have heard, I'm not
yet convinced, for example, that templates can be implemented
"correctly", for a sufficiently rigorous definition of "correctly".
(The specification for the context of instantiation is IMHO too vague.
And can probably not be made precise enough without specifying it in
terms of a rigorous module concept, which is missing in C++.)  The
second is whether the feature results in a provable abstraction.  Much
work on program proofs has been done concerning the program flow
generated by while or if -- use of these statements, rather than goto,
improves program reliability.  I would be interested in seeing similar
work concerning exceptions, or even more, virtual functions.  (Bertrand
Meyer has done some work in this direction, with the programming by
contract concept.  IMHO, it is sufficient for all but the most demanding
applications.  But in the end, I wouldn't trust my life to it.  For that
matter, the locomotive brake system used negative logic -- you needed to
maintain air preasure to keep the brakes released.  And the emergency
brake position physically pulled a stopper in the air line; the power
supply to the computer logic and the air pump ran through the stopper,
and was broken when the stopper was pulled.)

|>  >> The reductio ad absurdem for your argument would have us all coding in
|>  >> forth (language translator sizes down to 8k). Are you seriously
|>  >> suggesting this would result in applications with fewer errors ?
|>  >
|>  >Well, I know some people who claim this:-).
|>
|>  I don't.
|>
|>  ...snip...
|>
|>  >> No. We need *all of* the complexity of C++ (though not necessarily all
|>  >> in one file or even program). We need it for this reason :
|>
|>  ...snip...
|>
|>  >You may need all of those things; I currently need only full support for
|>  >OO (including garbage collection:-().
|>
|>  Garbage collection is not directly related to OO design, but much closer
|>  to dynamic allocation in general.

Garbage collection is related to OO design in that polymorphic objects
must almost always be allocated dynamically.  While it is a gros
simplification (i.e. a lie) to pretend that garbage collection comes
anywhere close to solving all of your memory management problems, it
does make the total effort significantly simpler.  (I often think that
what I need most is inverse garbage collection: I explicitly delete an
object, and all pointers to it are automatically null'ed.)

|>  It is ironic to hear somebody who is
|>  arguing for EC++ on (inter-alia) efficiency reasons rueing the omission
|>  of garbage collection from C++ when this was done precisely because it
|>  is hard to implement without adding an overhead to the language. If you
|>  think new and delete are out of the question for safety critical systems
|>  then wait till you see your system stop dead while it carries the trash
|>  out !

It's been years since I've seen a system stop dead because of garbage
collection.  On all of the garbage collected software I use (mainly
emacs), the garbage collector runs during waits for input.  There are
also strictly deterministic garbage collection systems, with
deterministic real time behavior.  (The standard new and delete of most
systems do not have deterministic behavior.)

Again, in this, I'm not arguing for or against EC++.  I'm arguing
against someone who said that anyone who doesn't need all of the new C++
features can't be doing OO.  And all I'm saying is that in the end, if
"doing OO" is the only critera, there are features even more important
that the ones that got added.

|>  >In my embedded systems, however,
|>  >typically, only limited support for OO was important (encapsulation and
|>  >objects are often important, polymorphism much less), and backward
|>  >compatibility with C was of no importance.  The time critical sections
|>  >were often written in assembler, as well, at least in the past.  (Today,
|>  >I think that writing C-level C++ would do the trick.)
|>
|>  Templates and inline virtual functions allow code to be written that is
|>  simultaneously high level and more efficient than is convenient to write
|>  in modular assambler language.
|>  I gave an example of this in comp.arch.embedded recently which you could
|>  probably still find on dejanews if you are interested.
|>
|>
|>  I repeat that there is no feature of C++ that will not be missed if it
|>  is removed from the language.

I would easily agree IF you add the words "by someone".  At least in the
applications I'm currently doing, and have done in the past, none of the
new template features would be missed.  (We do miss, however, the lack
of link time template instantiation, a la CFront.)  Namespaces won't be
missed.  In most cases, exceptions wouldn't be missed.  In the current
application, garbage collection WILL be missed, but this wasn't the case
for most preceding applications.

|>  People have tried to say in this thread that resource constrained
|>  embedded systems programmers will not miss various  features.
|>  I would say that we are exactly the people who will miss templates,
|>  exceptions, multiple inheritance etc.

If we ignore the safety critical applications for an instant (which are,
after all, the minority of embedded applications), it is still a
question of: is it worth the price?  In practice, exceptions are
probably out, because of space reasons.  The others could be
interesting, IF the price is low enough.  Given the present state of the
art, it isn't, but unlike exceptions, I see no fundamental reasons why
the situation cannot improve.  Hopefully, EC++ will evolve with it.
(This is one of the advantages of it not being an ISO standard.)

|>  More so than resource rich systems where it is ok to use a feature that
|>  inefficiently implemented (perhaps because written at the application
|>  level, perhaps because it hasn't had the time spent on it that is needed
|>  to make it efficient).

--
James Kanze    +33 (0)1 39 23 84 71    mailto: kanze@gabi-soft.fr
GABI Software, 22 rue Jacques-Lemercier, 78000 Versailles, France
Conseils en informatique orient   e objet --
              -- Beratung in objektorientierter Datenverarbeitung


[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Jonathan Biggar <jon@floorboard.com>
Date: 1998/06/23
Raw View
J. Kanze wrote:
> I'm no longer sure what comment triggered my remark, so it's hard to put
> it in context.  Out of context: as a simple rule, safety-critical
> systems must be 100% deterministic, and must be provably so.  IMHO, this
> rules out dynamic memory allocation (not because it isn't possible, but
> because it is significantly more expensive in terms of implementation
> effort than the alternatives), all indirection in program flow paths
> (e.g. virtual functions) and anything that violates the principle of
> single-entry/single-exit.

Outlawing virtual functions is simply silly.  If the program needs to be
able to have polymorphic behavior based on the type of the data
manipulated, using virtual functions, in the hands of a good programmer,
results in a cleaner, easier to understand and simpler to maintain
program.

If you outlaw virtual functions, you will end up with programs with
switch statements scattered all over the code, which makes the program
much harder to maintain, since the polymorphic behavior is not collected
together in each class definition.  On top of that, you have no
performance gain, since a switch statement is going to be at least as
costly as a virtual function call.

Your other two points, dynamic memory allocation, and exceptions (that
is what I assume you are aiming at when talking about
single-entry/single-exit) certainly do make proving the code harder, but
virtual functions do not.

--
Jon Biggar
Floorboard Software
jon@floorboard.com
jon@biggar.org
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: "Greg Colvin" <spam@me.not>
Date: 1998/06/23
Raw View
J. Kanze <kanze@gabi-soft.fr> wrote in article <m3d8c1ywqn.fsf_-_@gabi-soft.fr>...
> Mike Davies <mike_davies@noco.demon.co.uk> writes:
> |>  >In this case, you are simply wrong.  In hi-rel code, exceptions are
> |>  >generally banned, because proving exception safety is too difficult.

More precisely, I think, because the mathematics currently used for
reasoning about critical systems doesn't take exceptions into account.

> |>  No, I don't agree. It is completely trivial to make C++ code exception
> |>  safe : compile all modules with exceptions enabled and use the exception
> |>  enabled version of the library. Then wrap the contents of main() in a
> |>  try...catch block.

It's possible, but not that easy.  For example, if the destructor of a
container element throws an exception you get undefined behavior.

> See any number of back issues of C++ Reports; there was a number of
> articles concerning exception safety in them about a year or so ago.  In
> one of them (the first?), Tom Cargill "proved" it impossible to write a
> Stack class that was exception safe.

Tom proved only that a stack whose pop operation returns a reference to
the popped value cannot be safe.  The standard stack is safe.  The other
articles have mostly been outdated by progress in the standard, prompted
in part by those articles.
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]