Re: Why do some code bases don't use exceptions?
On Nov 26, 1:44 am, "dragan" <spambus...@prodigy.net> wrote:
James Kanze wrote:
On Nov 25, 11:03 am, "dragan" <spambus...@prodigy.net> wrote:
James Kanze wrote:
On Nov 23, 8:09 pm, "io_x" <a...@b.c.invalid> wrote:
"dragan" ha scritto nel
[....]
That's the whole point of exceptions. They're for the sort of
problems where it doesn't matter where the problem occured; the
handling is the same. If you run out of memory processing a
request, for example, it doesn't matter where you were in the
processing when you ran out; you just abort the request (but not
the process) with an error message, and continue.
You seem to be big on aborting.
Attention about word use. There's aborting (in the sense of
calling abort()), and aborting (in the more general sense,
of immediately terminating some action that you were in the
process of doing). In this case, I'm using the other sense:
say you've received a request on your LDAP server, and you
run out of memory trying to service it (because it requires
interpreting some obscenely complicated filter expression,
for example). When you detect the lack of memory, you're
down in some really deap parsing function, executing
operator new. You (or rather the system) raises an
std::bad_alloc exception, which you catch at the top level,
and abort the request (not the program), returning an error
message of "insufficient resources", or the like.
Ah. Bad choice of word then to describe that.
I didn't invent the language (English). I just use it. I don't
know of any other word for what I described; abort is the
standard word.
I think most people who see "abort" think exit the process or
terminate the thread.
I think most people read more than just a word at a time, and
the expression "abort the request" is quite clear. "Abort the
request" is not "abort the process".
Even in your example above though, I wouldn't expect abort to
occur unless the situation has been going on for some time.
The server should have preallocated some resources for use in
such situations.
I'm not sure I follow. The server will certainly have some
resources preallocated, so that it can successfully log the
error, unwind the stack, and return an error message. But by
definition, it can't use those resources for parsing the
request, or they won't be available for the things they were
reserved for.
A very valid pattern is fixing the problem and resuming.
If that's a valid reaction to the error, aborting isn't the
answer. If the error was a coding error, you can't fix the
source, recompile the code, and resume, so you abort. If
the error was insufficient memory due to an overly
complicated request, you can't simplify the request and
resume: you abort the operation. (On receiving an
"insufficient resources" error, of course, the client may
try a simpler request.)
Some version of Windows expands the stack that way: a
violation occurs when trying to push beyond the current
stack frame and the system catches the error, expands the
stack by 4k and continues processing.
(Isn't that how most systems work?
I don't know.
That's more or less the way the old Berkley kernel worked on
Sun 3's, and IIRC, PDP-11's memory manager unit was designed
expressedly to support something like this, back in the days
before virtual memory.)
I'm not too sure how that's relevant to user code, however.
Are you saying that if you get std::bad_alloc, you should
try to get more memory?
See my comment above.
Which one? Are you saying that if you get std::bad_alloc, you
should output a message to the terminal, asking the sysop to
insert additional memory chips, and only continue when he does?
Frankly, out of memory is a special case, and most of the
programs I've worked on installed a new_handler to abort in
such cases. Not all, however, and particularly on
transaction based systems where transactions can require a
lot of memory, it often makes sense to just abort the
transation. I can't think of much else you could do: call
some system routine to create more virtual memory?
Preallocate for use in those times. Could be from an entirely
different heap or something. Or hardware even: a mem card in a
PCI-X slot ... possibilities are endless. EH is
application-specific.
Preallocate what? Parsing an LDAP request requires unbounded
memory, since the request can be arbitrarily complicated: the
filter expression can contain any number of parenthesized
sub-expressions. It's just like a C or a C++ compiler: feed it
a file with a function which contains 2 billion nested
parentheses, and see what happens. You can't predict up front
how complex an expression will be, and how much memory you'll
need. Either you arbitrarily limit the complexity (for example,
to prevent stack overflow if you're using recursive descent), or
you handle insufficient memory. Or both: you might normally be
able to handle the expression, but not if a thousand or so
clients send it at the same time.
--
James Kanze