Christopher Smith wrote:
Well, you could provide a nice message back to the customer, or you
could be presenting them with someone else's credit card number. ;-)
Errr, no, I wouldn't think so, since the other person's credit card
wouldn't be in their address space, right?
get messed up anyway, but you have a good chance that the problem only
exists in your process.
Sure. And I have a good chance that in my program, the problem isn't one
that would keep my error handling from running correctly. Of course, if
it is, then I fall back to your solution, and exit.
Huh? How do you know that you'll get an error when something happens
that shouldn't?
Depending on what you mean by "error" and what you mean by "shouldn't",
of course I don't. But I know it more than you do, using C or C++. There
are a whole range of common errors it's impossible for me to encounter
using a safe language.
But if you don't have a way to catch errors in the first place (such as
array bounds checking, bounds checking on integers, and so on)
I assure you that C++ is capable of doing such things.
Sure, but you have to get it right Every Single Time.
written in C or C++. ;-) It's nice when a language does this stuff for
you, although it can be annoying when you can't turn it off when it gets
in your way, but then you can always switch to an unsafe language. ;-)
Yes, exactly my point.
If you're relying on a core dump to detect an error, my process will
dump core in exactly the same way as yours does if there's an error in
stdio or something.
Nah, 'cause your code will turn it in to an IO exception or a null
pointer exception, etc., unwind the stack a bit until it thinks it can
start all over again.
Well, not if there's an error in the interpreter. If an unsafe library
generates a segv, I'll get a segv.
And since you can catch signals in C, you're not guaranteed you'll dump
core either. So again, I don't see what the difference is.
Sure, but there are far more subtle errors that pretty much or only
going to show up in the form of your code finding itself in an
unexpected state.
Certainly. I've had bad sectors in swap space.
That is not exactly a subtle error.
You would be amazed. When's the last time you checked your swap space
for errors? What if there's a read error one out of say 1000 times?
No, but you probably have two issues to consider: 1) my math is totally
broken, and I gotta stop what I'm doing, figure out how exactly how this
happened, and fix it before all hell breaks loose or 2) some kind of bug
in the "unsafe" portion of the code has put my entire program in an
unsafe state, so notions of safety are now out the window and I gotta
stop what I'm doing, figure out exactly how this happened, and fix it
before all hell breaks loose. Oddly enough, the results are the same.
Except the "unsafe" portion of my code is either extremely well tested
(not unlike relying on the kernel) or a tiny portion of my code. If I
very carefully craft the 2% that's unsafe and go hog wild on the 98%
that's safe, I can be much more productive than if I have to carefully
craft the 100% of the application.
Why do you need a range-checking language?
Because running outside an array is a huge cause of errors, and if I can
have my language or compiler check that instead of doing it by hand,
it's both more efficient and safer.
Hmm... let me place some emphasis in that sentence for clarity:
Why do you need a range-checking *language*.
To ensure that the range checks actually get checked everywhere. The
same reason you want your compiler to enforce the syntax of your
language, and the type checking, and so on. It reduces the number of
unsafe places you need to check for unsafe behavior to just those places
that *need* to be unsafe.
In C++ it is not at all uncommon for folks to use collections and
iterators that do range checking. It is done in the library, rather than
in the language, following the pearl of wisdom that if you can do
something in a library instead of the syntax of a language, it's a good
thing.
Sure. Until some unsafe library clobbers your collection somewhere else,
and you start getting stuff out of the collection that you never put in,
and you spend a month tracking down what's going on. BTDTGTTS.
I think you missed my point. I'm not questioning that automatic range
checking is useful. I'm just questioning why it has to be embedded in to
the definition of the syntax of a programming language.
It's not embedded in the syntax of the languages I use that are safe.
Neither Tcl nor Smalltalk (for example) define a syntax for arrays. I
wouldn't say it's in the "syntax" of Java either. Java just defines what
happens. My language is my library, and I don't make a really big
distinction between the two. That Zen bit again.
> I write C++ code
that automatically checks against range boundaries, null pointers,
integer overflows and all kinds of other badness. Indeed by doing so I
can automatically catch a lot of errors that go undetected in a number
of "safe" languages without manual coding.
You mean, you use libraries that other people wrote? Because otherwise,
that's manual coding. And if you're using libraries others wrote for
this, how do you know they're right and safe? And if you actually manage
to catch every one of those types of errors, and you then write an
automated tool to enforce that you only use those templates, you know
what you just did? You just implemented a safe language in C++. Go for it.
And, on the subject, how do you build a data structure that's an
arbitrary graph in C++ and still manage to garbage collect it when
you're done with the last reference to it?
Safe language != stack never gets corrupted. I can tell you this from a
lot of first hand experience.
Bad implementation of safe language might mean stack gets corrupted. Bad
implementation of OS means files get corrupted. So? How likely is that,
compared to a bug in your code? Why is it more likely a bug in the
language interpreter than a bug in the C runtime, the kernel, a device
driver, or some chunk of hardware?
Actually, just the opposite. If I have a "safe" language, and I find a
value or condition that is defined to not be possible, I actually have
all the more reason to assume the worst.
Uh, like what? Sure, if you have something defined to be impossible,
then it's a good time to exit. But I can't think offhand of any
condition defined to be "impossible" in the languages I know of that's
ever likely to come up. That's kind of what a "safe" language means -
there's a defined result for anything you can do within the language.
Now you can avoid that error in C++ (not to mention abusing pointer
arithmetic). You're welcome.
If you're not going to grant me that a safe language can be relied upon
to not produce "impossible" results, why should I grant you that the
code you just supplied will actually prevent null pointer exceptions?
Maybe your compiler is broken, or some library you're using clobbers the
pointer, or some other thread screws with the pointer between the test
and the invocation, or ....
I'm not sure why recovery code at the top level of the stack needs to be
held to a higher standard than recovery code lower down.
Well, it depends on what you mean by "lower down", but hopefully code
that is local to the error understands the nature of the problem and can
correct it or at least avoid it.
Sure, if you think of it. That's the goal of catching the unexpected
errors - to fix the code so they're expected errors.
--
Darren New / San Diego, CA, USA (PST)
His kernel fu is strong.
He studied at the Shao Linux Temple.
--
[email protected]
http://www.kernel-panic.org/cgi-bin/mailman/listinfo/kplug-lpsg