Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #18090 > unrolled thread
| Started by | Don Y <this@isnotme.com> |
|---|---|
| First post | 2012-03-01 12:48 -0700 |
| Last post | 2012-03-06 11:21 -0700 |
| Articles | 20 on this page of 87 — 17 participants |
Back to article view | Back to comp.lang.c
Mechanism to generate annotated "error codes" Don Y <this@isnotme.com> - 2012-03-01 12:48 -0700
Re: Mechanism to generate annotated "error codes" Willem <willem@toad.stack.nl> - 2012-03-01 21:29 +0000
Re: Mechanism to generate annotated "error codes" Don Y <this@isnotme.com> - 2012-03-01 16:53 -0700
Re: Mechanism to generate annotated "error codes" William Ahern <william@wilbur.25thandClement.com> - 2012-03-01 14:13 -0800
Re: Mechanism to generate annotated "error codes" Don Y <this@isnotme.com> - 2012-03-01 22:07 -0700
Re: Mechanism to generate annotated "error codes" Shao Miller <sha0.miller@gmail.com> - 2012-03-01 17:53 -0500
Re: Mechanism to generate annotated "error codes" Don Y <this@isnotme.com> - 2012-03-01 23:05 -0700
Re: Mechanism to generate annotated "error codes" Shao Miller <sha0.miller@gmail.com> - 2012-03-02 01:50 -0500
Re: Mechanism to generate annotated "error codes" Don Y <this@isnotme.com> - 2012-03-02 00:43 -0700
Re: Mechanism to generate annotated "error codes" Shao Miller <sha0.miller@gmail.com> - 2012-03-03 17:58 -0500
Re: Mechanism to generate annotated "error codes" Shao Miller <sha0.miller@gmail.com> - 2012-03-04 03:16 -0500
Re: Mechanism to generate annotated "error codes" Don Y <this@isnotme.com> - 2012-03-04 13:47 -0700
Re: Mechanism to generate annotated "error codes" Don Y <this@isnotme.com> - 2012-03-04 13:45 -0700
Re: Mechanism to generate annotated "error codes" Shao Miller <sha0.miller@gmail.com> - 2012-03-04 18:37 -0500
Re: Mechanism to generate annotated "error codes" Don Y <this@isnotme.com> - 2012-03-04 22:12 -0700
Re: Mechanism to generate annotated "error codes" Shao Miller <sha0.miller@gmail.com> - 2012-03-08 01:41 -0500
Re: Mechanism to generate annotated "error codes" Don Y <this@isnotme.com> - 2012-03-09 14:34 -0700
Re: Mechanism to generate annotated "error codes" Don Y <this@isnotme.com> - 2012-03-02 00:30 -0700
Re: Mechanism to generate annotated "error codes" Keith Thompson <kst-u@mib.org> - 2012-03-02 02:05 -0800
Re: Mechanism to generate annotated "error codes" Kaz Kylheku <kaz@kylheku.com> - 2012-03-02 10:47 +0000
Re: Mechanism to generate annotated "error codes" gazelle@shell.xmission.com (Kenny McCormack) - 2012-03-02 14:18 +0000
Re: Mechanism to generate annotated "error codes" Don Y <this@isnotme.com> - 2012-03-02 10:46 -0700
Re: Mechanism to generate annotated "error codes" James Kuyper <jameskuyper@verizon.net> - 2012-03-02 14:08 -0500
Re: Mechanism to generate annotated "error codes" Don Y <this@isnotme.com> - 2012-03-02 12:38 -0700
Re: Mechanism to generate annotated "error codes" Kaz Kylheku <kaz@kylheku.com> - 2012-03-02 22:57 +0000
Re: Mechanism to generate annotated "error codes" Don Y <this@isnotme.com> - 2012-03-02 17:14 -0700
Re: Mechanism to generate annotated "error codes" Kaz Kylheku <kaz@kylheku.com> - 2012-03-03 02:25 +0000
Re: Mechanism to generate annotated "error codes" James Kuyper <jameskuyper@verizon.net> - 2012-03-03 06:10 -0500
Re: Mechanism to generate annotated "error codes" Shao Miller <sha0.miller@gmail.com> - 2012-03-03 16:12 -0500
Re: Mechanism to generate annotated "error codes" Keith Thompson <kst-u@mib.org> - 2012-03-03 04:04 -0800
Re: Mechanism to generate annotated "error codes" Kaz Kylheku <kaz@kylheku.com> - 2012-03-03 15:05 +0000
Re: Mechanism to generate annotated "error codes" Ben Bacarisse <ben.usenet@bsb.me.uk> - 2012-03-03 16:25 +0000
Re: Mechanism to generate annotated "error codes" Shao Miller <sha0.miller@gmail.com> - 2012-03-03 16:26 -0500
Re: Mechanism to generate annotated "error codes" Keith Thompson <kst-u@mib.org> - 2012-03-03 13:40 -0800
Re: Mechanism to generate annotated "error codes" Ian Collins <ian-news@hotmail.com> - 2012-03-03 12:03 +1300
Re: Mechanism to generate annotated "error codes" Keith Thompson <kst-u@mib.org> - 2012-03-02 15:45 -0800
Re: Mechanism to generate annotated "error codes" Don Y <this@isnotme.com> - 2012-03-02 17:18 -0700
Re: Mechanism to generate annotated "error codes" blp@cs.stanford.edu (Ben Pfaff) - 2012-03-02 15:08 -0800
Re: Mechanism to generate annotated "error codes" "BartC" <bc@freeuk.com> - 2012-03-03 10:30 +0000
Re: Mechanism to generate annotated "error codes" James Kuyper <jameskuyper@verizon.net> - 2012-03-03 06:19 -0500
Re: Mechanism to generate annotated "error codes" Phil Carmody <thefatphil_demunged@yahoo.co.uk> - 2012-03-03 15:15 +0200
Re: Mechanism to generate annotated "error codes" Kaz Kylheku <kaz@kylheku.com> - 2012-03-03 14:52 +0000
Re: Mechanism to generate annotated "error codes" Malcolm McLean <malcolm.mclean5@btinternet.com> - 2012-03-03 07:39 -0800
Re: Mechanism to generate annotated "error codes" Jonathan Leffler <jleffler@earthlink.net> - 2012-03-03 23:56 -0800
Re: Mechanism to generate annotated "error codes" Ian Collins <ian-news@hotmail.com> - 2012-03-05 09:20 +1300
Re: Mechanism to generate annotated "error codes" Malcolm McLean <malcolm.mclean5@btinternet.com> - 2012-03-04 13:28 -0800
Re: Mechanism to generate annotated "error codes" Ian Collins <ian-news@hotmail.com> - 2012-03-05 10:56 +1300
Re: Mechanism to generate annotated "error codes" "BartC" <bc@freeuk.com> - 2012-03-03 17:02 +0000
Re: Mechanism to generate annotated "error codes" Keith Thompson <kst-u@mib.org> - 2012-03-03 12:30 -0800
Re: Mechanism to generate annotated "error codes" Don Y <this@isnotme.com> - 2012-03-03 19:15 -0700
Re: Mechanism to generate annotated "error codes" Kaz Kylheku <kaz@kylheku.com> - 2012-03-04 03:20 +0000
Re: Mechanism to generate annotated "error codes" Don Y <this@isnotme.com> - 2012-03-04 11:03 -0700
Re: Mechanism to generate annotated "error codes" Don Y <this@isnotme.com> - 2012-03-04 16:31 -0700
Re: Mechanism to generate annotated "error codes" Don Y <this@isnotme.com> - 2012-03-04 23:04 -0700
Re: Mechanism to generate annotated "error codes" Malcolm McLean <malcolm.mclean5@btinternet.com> - 2012-03-02 22:13 -0800
Re: Mechanism to generate annotated "error codes" Don Y <this@isnotme.com> - 2012-03-03 00:49 -0700
Re: Mechanism to generate annotated "error codes" Malcolm McLean <malcolm.mclean5@btinternet.com> - 2012-03-03 03:32 -0800
Re: Mechanism to generate annotated "error codes" Don Y <this@isnotme.com> - 2012-03-03 12:04 -0700
Re: Mechanism to generate annotated "error codes" Lowell Gilbert <lgusenet@be-well.ilk.org> - 2012-03-03 15:06 -0500
Re: Mechanism to generate annotated "error codes" Don Y <this@isnotme.com> - 2012-03-03 14:38 -0700
Re: Mechanism to generate annotated "error codes" Malcolm McLean <malcolm.mclean5@btinternet.com> - 2012-03-03 12:15 -0800
Re: Mechanism to generate annotated "error codes" Don Y <this@isnotme.com> - 2012-03-03 16:51 -0700
Re: Mechanism to generate annotated "error codes" Malcolm McLean <malcolm.mclean5@btinternet.com> - 2012-03-04 14:08 -0800
Re: Mechanism to generate annotated "error codes" Don Y <this@isnotme.com> - 2012-03-04 15:56 -0700
Re: Mechanism to generate annotated "error codes" Malcolm McLean <malcolm.mclean5@btinternet.com> - 2012-03-03 03:45 -0800
Re: Mechanism to generate annotated "error codes" Lowell Gilbert <lgusenet@be-well.ilk.org> - 2012-03-03 14:11 -0500
Re: Mechanism to generate annotated "error codes" Don Y <this@isnotme.com> - 2012-03-03 13:03 -0700
Re: Mechanism to generate annotated "error codes" Don Y <this@isnotme.com> - 2012-03-03 12:32 -0700
Re: Mechanism to generate annotated "error codes" Don Y <this@isnotme.com> - 2012-03-03 15:04 -0700
Re: Mechanism to generate annotated "error codes" Ian Collins <ian-news@hotmail.com> - 2012-03-04 11:09 +1300
Re: Mechanism to generate annotated "error codes" Don Y <this@isnotme.com> - 2012-03-03 16:55 -0700
Re: Mechanism to generate annotated "error codes" Ian Collins <ian-news@hotmail.com> - 2012-03-04 13:04 +1300
Re: Mechanism to generate annotated "error codes" Don Y <this@isnotme.com> - 2012-03-03 18:24 -0700
Re: Mechanism to generate annotated "error codes" Malcolm McLean <malcolm.mclean5@btinternet.com> - 2012-03-03 14:30 -0800
Re: Mechanism to generate annotated "error codes" Don Y <this@isnotme.com> - 2012-03-03 17:06 -0700
Re: Mechanism to generate annotated "error codes" Ian Collins <ian-news@hotmail.com> - 2012-03-05 10:09 +1300
Re: Mechanism to generate annotated "error codes" Don Y <this@isnotme.com> - 2012-03-04 16:03 -0700
Re: Mechanism to generate annotated "error codes" Ian Collins <ian-news@hotmail.com> - 2012-03-05 13:26 +1300
Re: Mechanism to generate annotated "error codes" Don Y <this@isnotme.com> - 2012-03-04 22:21 -0700
Re: Mechanism to generate annotated "error codes" Ian Collins <ian-news@hotmail.com> - 2012-03-05 20:46 +1300
Re: Mechanism to generate annotated "error codes" Don Y <this@isnotme.com> - 2012-03-05 10:54 -0700
Re: Mechanism to generate annotated "error codes" Ian Collins <ian-news@hotmail.com> - 2012-03-06 10:02 +1300
Re: Mechanism to generate annotated "error codes" Don Y <this@isnotme.com> - 2012-03-05 16:09 -0700
Re: Mechanism to generate annotated "error codes" "BartC" <bc@freeuk.com> - 2012-03-06 10:54 +0000
Re: Mechanism to generate annotated "error codes" Ian Collins <ian-news@hotmail.com> - 2012-03-07 07:22 +1300
Re: Mechanism to generate annotated "error codes" gordonb.8sa24@burditt.org (Gordon Burditt) - 2012-03-06 08:51 -0600
Re: Mechanism to generate annotated "error codes" Don Y <this@isnotme.com> - 2012-03-06 11:21 -0700
Page 4 of 5 — ← Prev page 1 2 3 [4] 5 Next page →
| From | Malcolm McLean <malcolm.mclean5@btinternet.com> |
|---|---|
| Date | 2012-03-03 12:15 -0800 |
| Message-ID | <a98e08c8-a382-4561-8fb1-259bffef3404@f2g2000yqh.googlegroups.com> |
| In reply to | #18153 |
On Mar 3, 7:04 pm, Don Y <t...@isnotme.com> wrote:
>> That was the point I was trying to bring out. Do you call the
> "parameter" passed to it a "programming error"? That would imply
> the caller had the responsibility of checking it for correctness
> (eliminating the need for the parser's functionality).
>
You have to specify that in the "contract". To say that "the result of
passing a negative number to square root is undefined" is reasonable.
So then the code can loop forever, because it never converges on root
x. But that doesn't have to be the contract. You could say that "the
result of passing a negative number will always be NaN". Then
if(datamissing) return sqrt(-1); /* generate a NaN */ is correct
code.
To say "this function must be passed a valid Basic program" is
probably unreasonable. But again it depends on the situation.
>
> I think "expect" is overly cynical. I would say "you PREPARE FOR
> <any input> to be 'malformed'" -- since you can't control the
> outside world.
>
In the case of a non-trival script in any programming language,
written by a human, first time it is automatically checked by a
machine almost certainly an error of some sort will be uncovered. In
the case of sqrt(), most experienced programmers know that generally
machines can't handle imaginary numbers and that sqrt(-1) * sqrt(-1)
won't yield the mathematically correct result.
>
> Returning to my original example (scanning a string of chars to
> extract the numeric value expected to be represented therein),
> that function (pure function using your terminology) can report
> the nature of any "incompatible input" to any degree of detail
> that it considers appropriate. Not just "hey, I couldn't find
> a valid 'number' in this mess..."
>
> Those reports make sense in the context of a function that
> is responsible for extracting the numeric value represented by a
> string of characters. REGARDLESS OF WHAT THAT NUMBER IS BEING
> USED FOR. And, regardless of the actual value!
>
So somewhere in the code we have a function
bool isvalidnumber(char *str)
calling that function with any C string whatsoever is not a
programming error. Having called that function, you can then call atoi
(which has undefined behaviour on overflow) or strtod().
If isvalidnumber() return false, and you are expecting a number in the
input, that's a parse error
>
> E.g., if that routine also had the responsibility of testing that
> the value was within a particular set of bounds, it could add
> "Value specified exceeds the maximum allowed.", etc. to its
> lexicon of errors.
>
> None of these reports need to know whether the "value" is being
> used as a representation of AGE, azimuth/elevation, speed,
> stock market index, etc. You are dealing with a *value* -- just
> like when you complain that the first letter of a sentence is
> not capitalized (you don't even look at the CONTENT of the
> sentence to understand the nature of that "report").
>
> But, you obviously don't want that "pure function" to become
> a "procedure" by virtue of informing the user directly of
> this error (this would also badly contort the design of
> your code).
>
Exactly. So you pass errors like that up and up, until you reach a
procedure. The procedure then has access to IO, and can tell the user
that it expected a number but found a non-numerical string. There is a
problem of how to make the message informative - sometimes "parse
error reading input file" is all you want, sometimes you want the line
number, sometimes you want to print the offending string. Low-level
functions to extract numbers can't sensibly take these decisions.
>
> Nor do you need to return the text of the message to the caller!
> (how do you decide whether you should return the en_US version
> of the message or the es version?)
>
> Instead, return an identifier that allows the caller to fetch
> a version of the error that *it* considers appropriate.
>
> It, in turn, can embellish -- or replace -- that message with
> something appropriate to its understanding of the application.
> E.g., perhaps the caller is responsible for obtaining the
> coordinates of a point in 2D space. It *uses* the called routine
> to parse the string (that is provided to *it* by ITS caller!)
> for the X coordinate, then the Y coordinate. An error reported
> during the first parse might cause it to report an error to
> *it's* caller like: "Bad value for X coordinate." AUGMENTED
> by the report returned by the function that had actually
> detected the lower level error "Non-numeric character encountered
> in value."
>
It's found a non-numerical string for the x co-ordinate. So processing
should normally stop at that point. The NaN x co-ordianate should
never be passed to the triangle drawing routine. There are problems if
we have someting like this
draw_triangle( void (*get_point)(double *x, double *y) )
{
}
because get_point() has no way of passing the error condition up the
call chain.
>
> Or not (depends on the range of errors that you document
> get_point() as reporting). You could, instead, ignore the
> detail presented to you by any of your "underlings" and
> just report: "Bad point".
>
>
You do that, but you don't need a centralised error system. The errors
are part of the contract between caller and function.
[toc] | [prev] | [next] | [standalone]
| From | Don Y <this@isnotme.com> |
|---|---|
| Date | 2012-03-03 16:51 -0700 |
| Message-ID | <jiuaqg$dme$1@speranza.aioe.org> |
| In reply to | #18161 |
Hi Malcolm,
On 3/3/2012 1:15 PM, Malcolm McLean wrote:
> On Mar 3, 7:04 pm, Don Y<t...@isnotme.com> wrote:
>
>>> That was the point I was trying to bring out. Do you call the
>> "parameter" passed to it a "programming error"? That would imply
>> the caller had the responsibility of checking it for correctness
>> (eliminating the need for the parser's functionality).
>
> You have to specify that in the "contract". To say that "the result of
Yes, of course. The point I was illustrating is you tend to want to
*hide* detail, not expose it. (Divide and Conquer)
> passing a negative number to square root is undefined" is reasonable.
> So then the code can loop forever, because it never converges on root
Exactly. When preparing a specification for a client, any time they
respond "I don't care" to one of my questions, I say, sotto voce,
"In the case of ______, crash and burn."
Amazing how quickly people start to "care"! :>
> x. But that doesn't have to be the contract. You could say that "the
> result of passing a negative number will always be NaN". Then
> if(datamissing) return sqrt(-1); /* generate a NaN */ is correct
> code.
> To say "this function must be passed a valid Basic program" is
> probably unreasonable. But again it depends on the situation.
Exactly. I was drawing attention to your partitioning of pure
vs. I/O capable functions and the constraints you placed on
providing "correct input".
[In fact, I litter the preamble of each function with a littany
of assertions to catch any such violations as well as make them
crystal clear: In case the developer might not have understood
the written specification, *this* is what it boils down to!]
>> I think "expect" is overly cynical. I would say "you PREPARE FOR
>> <any input> to be 'malformed'" -- since you can't control the
>> outside world.
>
> In the case of a non-trival script in any programming language,
> written by a human, first time it is automatically checked by a
> machine almost certainly an error of some sort will be uncovered. In
> the case of sqrt(), most experienced programmers know that generally
> machines can't handle imaginary numbers and that sqrt(-1) * sqrt(-1)
> won't yield the mathematically correct result.
Yes, but there is a wide world of other possibilities and users
out there. If, for example, you prohibit leading zeroes in a
value, someone typing in "0001" might be surprised to see it
rejected.
>> Returning to my original example (scanning a string of chars to
>> extract the numeric value expected to be represented therein),
>> that function (pure function using your terminology) can report
>> the nature of any "incompatible input" to any degree of detail
>> that it considers appropriate. Not just "hey, I couldn't find
>> a valid 'number' in this mess..."
>>
>> Those reports make sense in the context of a function that
>> is responsible for extracting the numeric value represented by a
>> string of characters. REGARDLESS OF WHAT THAT NUMBER IS BEING
>> USED FOR. And, regardless of the actual value!
>
> So somewhere in the code we have a function
>
> bool isvalidnumber(char *str)
>
> calling that function with any C string whatsoever is not a
> programming error. Having called that function, you can then call atoi
> (which has undefined behaviour on overflow) or strtod().
Except the "isvalidnumber" functionality is folded into the
"atoi/strtod" function. So, that composite function has to
be able to report parsing problems as well as conversion
problems (overflow, loss of significant digits, etc.)
> If isvalidnumber() return false, and you are expecting a number in the
> input, that's a parse error
>
>> E.g., if that routine also had the responsibility of testing that
>> the value was within a particular set of bounds, it could add
>> "Value specified exceeds the maximum allowed.", etc. to its
>> lexicon of errors.
>>
>> None of these reports need to know whether the "value" is being
>> used as a representation of AGE, azimuth/elevation, speed,
>> stock market index, etc. You are dealing with a *value* -- just
>> like when you complain that the first letter of a sentence is
>> not capitalized (you don't even look at the CONTENT of the
>> sentence to understand the nature of that "report").
>>
>> But, you obviously don't want that "pure function" to become
>> a "procedure" by virtue of informing the user directly of
>> this error (this would also badly contort the design of
>> your code).
>
> Exactly. So you pass errors like that up and up, until you reach a
> procedure. The procedure then has access to IO, and can tell the user
> that it expected a number but found a non-numerical string. There is a
> problem of how to make the message informative - sometimes "parse
> error reading input file" is all you want, sometimes you want the line
> number, sometimes you want to print the offending string. Low-level
> functions to extract numbers can't sensibly take these decisions.
I've ignored the issue of providing "supporting data" for the
message in this discussion (it's already too complicated! :> ).
But, anything that an upper level would *want* to obtain for
"report augmentation" would have to be made available to it
by the appropriate underlings.
E.g., my "malloc" is highly parametrized. You specify the
heap against which the request is made, the allocation policy
to use, the selection policy, etc. To simply return "NULL"
for any sort of error does very little to helping the user *or*
the developer/helpdesk sort out the exact nature of the problem.
>> Nor do you need to return the text of the message to the caller!
>> (how do you decide whether you should return the en_US version
>> of the message or the es version?)
>>
>> Instead, return an identifier that allows the caller to fetch
>> a version of the error that *it* considers appropriate.
>>
>> It, in turn, can embellish -- or replace -- that message with
>> something appropriate to its understanding of the application.
>> E.g., perhaps the caller is responsible for obtaining the
>> coordinates of a point in 2D space. It *uses* the called routine
>> to parse the string (that is provided to *it* by ITS caller!)
>> for the X coordinate, then the Y coordinate. An error reported
>> during the first parse might cause it to report an error to
>> *it's* caller like: "Bad value for X coordinate." AUGMENTED
>> by the report returned by the function that had actually
>> detected the lower level error "Non-numeric character encountered
>> in value."
>
> It's found a non-numerical string for the x co-ordinate. So processing
> should normally stop at that point. The NaN x co-ordianate should
> never be passed to the triangle drawing routine. There are problems if
> we have someting like this
>
> draw_triangle( void (*get_point)(double *x, double *y) )
> {
> }
> because get_point() has no way of passing the error condition up the
> call chain.
get_point would return an error indication/report. draw_triangle would
*also* return an error indication/report. "Turtles all the way down!"
Eventually, something would "handle" the error and decide how to
continue -- prompt for a new "triangle", etc.
(You have to *plan* how you are going to handle errors. You can't
just squeeze that in after-the-fact)
>> Or not (depends on the range of errors that you document
>> get_point() as reporting). You could, instead, ignore the
>> detail presented to you by any of your "underlings" and
>> just report: "Bad point".
>
> You do that, but you don't need a centralised error system. The errors
> are part of the contract between caller and function.
Yes. The centralization deals with how the errors/reports are
"bound to human readable terms". I.e., the messages, explanations
and remedies.
A 1960's style program would just spit out "error 2345" and quit.
My goal is to present locale-specific error messages in increasing
levels of detail (an experienced user only needs a brief message
to know what he did wrong; a novice might need their hands held)
along with explanations for the "error report" and possible remedies.
I.e., smart applications that don't just perform a task but do
so in a way that facilitates the user's performance of that task.
As I said, the (run-time) mechanism is not the problem. I've
already got that working well.
The problem lies with the compile time support. Making it
robust *and* efficient.
The semantics of the whole thing constrain what a developer
should -- and should *not* -- be able to do. The mechanism
should enforce those semantics.
E.g., an error code isn't a number. It isn't a string. It's
an ERROR CODE. A number or a string might *represent* a
particular error code but the semantics of numbers/strings
don't (and CAN'T!) translate to error codes themselves.
An error code is always a constant. You can't "alter" an
error code. OTOH, you can create a container to hold an
error code. You can copy that representation to a similarly
typed container. etc.
You can check to see if two error codes are equivalent
(whatever that means). But, there are no ordering operators
to *rank* error codes.
You can determine if an error code (again, "result" is a better
choice of term) represents a true "error", a "warning" (i.e.,
a qualified success) or actual "success". But, there are
no ordering relationships among these classifications other
than error != success, warning != error, etc.
You can't perform arithmetic on error codes.
You can't perform string operations on error codes.
You can't *duplicate* error codes (though you can have multiple
references to a particular error code).
You can't take the address of an error code (though you can
get a pointer to an error code container!).
You can't dereference an error code.
So, any implementation scheme that equivalences particular error codes
to other "normal" C constructs is suspect.
For example:
#define Err_NoMemory (23)
opens the door for:
if (Err_NoMemoy + 2 < 90) {
which doesn't make sense -- it relies on some magical, NONGUARANTEED
aspect that the developer *thinks* relates to "90" and "2" in some
way.
Or:
const char Err_NoMemory = "Insufficient Memory";
being exploited as:
printf("There is %s to perform your task.", Err_NoMemory)
Etc. (I'm sure you can extrapolate this sort of problem).
So, this limits where you can expose the error code in the source
file. Note how jarring the visual syntax of my examples have been
wrt MakeErrorCode usage:
if (size > MAX_ALLOCATION) {
MakeErrorCode(Err_TooBig,
"Allocation too large.",
"The requested piece of memory was larger than the
maximum supported for the process."
)
*error = Err_TooBig;
}
OK, I could preface the MakeErrorCode invocation with some leading
whitespace:
if (size > MAX_ALLOCATION) {
MakeErrorCode(Err_TooBig,
"Allocation too large.",
"The requested piece of memory was larger than the
maximum supported for the process."
)
*error = Err_TooBig;
}
But, what you *really* want to do is:
if (size > MAX_ALLOCATION) {
*error = MakeErrorCode(Err_TooBig,
"Allocation too large.",
"The requested piece of memory was "
"larger than the maximum supported
"for the process."
)
}
[apologies for all the whitespace if you are using a proportional
typeface]
But, this invites MakeErrorCode() being used in expressions
(you can do things to prevent this).
And, most of all, means any tool you develop to implement this
functionality (create a unique error code named by the first
parameter, squirrel away the explanations offered by the other
parameters, mark it as an ERROR and not a WARNING, etc.) now
has to understand C syntax.
Ah, wait! Let's have the preprocessor run through the source
(since it understands C). Then, extract the necessary parameters
from that macro (having been flagged in the preprocessed output),
*then* we can actually worry about compiling the module!
Hmmm... the source needs to be rewritten to make the "value"
of Err_NoMemory available. And, what if it also requires other
error codes defined in other modules?
I.e., this gets expensive -- though it can still be automated
and run well on today's faster machines. It just doesn;t
scale well.
I have another approach that I am implementing that should make
a lot of these issues go away. But, it still feels klunky.
(The ideal would be to build the support into the compiler
but that ties you to *that* compiler! Processing source
files in a separate tool is more flexible)
[toc] | [prev] | [next] | [standalone]
| From | Malcolm McLean <malcolm.mclean5@btinternet.com> |
|---|---|
| Date | 2012-03-04 14:08 -0800 |
| Message-ID | <8e192ddd-2064-4d5c-ac45-60416cf31205@b1g2000yqb.googlegroups.com> |
| In reply to | #18174 |
On Mar 3, 11:51 pm, Don Y <t...@isnotme.com> wrote: > > You can check to see if two error codes are equivalent > (whatever that means). But, there are no ordering operators > to *rank* error codes. > But some are supersets of others. DISK_FULL is an IO_ERROR is a SAVE_FAILED error. But of course IO_ERROR could also be a LOAD_FAILED error. So there's not strict nesting, unless you carefully define it to be so.
[toc] | [prev] | [next] | [standalone]
| From | Don Y <this@isnotme.com> |
|---|---|
| Date | 2012-03-04 15:56 -0700 |
| Message-ID | <jj0rus$bms$1@speranza.aioe.org> |
| In reply to | #18209 |
Hi Malcolm,
On 3/4/2012 3:08 PM, Malcolm McLean wrote:
> On Mar 3, 11:51 pm, Don Y<t...@isnotme.com> wrote:
>>
>> You can check to see if two error codes are equivalent
>> (whatever that means). But, there are no ordering operators
>> to *rank* error codes.
>>
> But some are supersets of others. DISK_FULL is an IO_ERROR is a
> SAVE_FAILED error. But of course IO_ERROR could also be a LOAD_FAILED
> error. So there's not strict nesting, unless you carefully define it
> to be so.
Yes. That's the responsibility of <whatever> detects the
"condition" and repackages it. There's no need (IMO) to
provide tools by which a developer can ask:
isSupersetOf(DISK_FULL, IO_ERROR);
The scheme I am outlining doesn't *eliminate* careful thought
regarding what an error *is* or how they should be structured.
Rather, it tries to automate the drudgery that would otherwise
discourage developers from spending *any* time trying to report
anything other than one of a *handful* of errors -- as NUMBERS!
[toc] | [prev] | [next] | [standalone]
| From | Malcolm McLean <malcolm.mclean5@btinternet.com> |
|---|---|
| Date | 2012-03-03 03:45 -0800 |
| Message-ID | <71e9ea6e-f120-48e3-b139-ac68447963db@f2g2000yqh.googlegroups.com> |
| In reply to | #18135 |
On Mar 3, 7:49 am, Don Y <t...@isnotme.com> wrote: > > > Centralised error systems mean that code will break if you try to move > > it to a different project. > > And, when our images are merged, we magically end up with the > union of error messages and "codes" that we have individually > used. > You've described the problem. Fred scatters his code with log_error(ERR_TOOMANYFILESOPEN); Bert does the same with fprintf_error(EC_FILECOUNTEXCEEDED, "Too many files open (%d)\n", Nfiles); Now when we merge Fred's code with Bert's, what's going to happen?
[toc] | [prev] | [next] | [standalone]
| From | Lowell Gilbert <lgusenet@be-well.ilk.org> |
|---|---|
| Date | 2012-03-03 14:11 -0500 |
| Message-ID | <44sjhp8pp3.fsf@lowell-desk.lan> |
| In reply to | #18140 |
Malcolm McLean <malcolm.mclean5@btinternet.com> writes: > On Mar 3, 7:49 am, Don Y <t...@isnotme.com> wrote: >> >> > Centralised error systems mean that code will break if you try to move >> > it to a different project. >> >> And, when our images are merged, we magically end up with the >> union of error messages and "codes" that we have individually >> used. >> > You've described the problem. > > Fred scatters his code with > > log_error(ERR_TOOMANYFILESOPEN); > > Bert does the same with > > fprintf_error(EC_FILECOUNTEXCEEDED, "Too many files open (%d)\n", > Nfiles); > > Now when we merge Fred's code with Bert's, what's going to happen? That's the wrong question, because the answer necessarily depends on the relationship between Fred and Bert. If they are independent third-party library developers, you're not likely to get them to use *your* error- reporting system now. If they both work for you, then you can require them to use any system you want, and any sane system should work (although simpler systems may be more effort to scale up). In practice, the former case usually means that each set of third-party code has its own type for errors, and the functions you call them from will report errors upwards according to their own convention that need have nothing to do with the third-party code. But you're limited to the information that their API already provide. -- Lowell Gilbert, embedded/networking software engineer http://be-well.ilk.org/~lowell/
[toc] | [prev] | [next] | [standalone]
| From | Don Y <this@isnotme.com> |
|---|---|
| Date | 2012-03-03 13:03 -0700 |
| Message-ID | <jittf4$bf7$1@speranza.aioe.org> |
| In reply to | #18154 |
Hi Lowell,
On 3/3/2012 12:11 PM, Lowell Gilbert wrote:
> Malcolm McLean<malcolm.mclean5@btinternet.com> writes:
>
>> On Mar 3, 7:49 am, Don Y<t...@isnotme.com> wrote:
>>>
>>>> Centralised error systems mean that code will break if you try to move
>>>> it to a different project.
>>>
>>> And, when our images are merged, we magically end up with the
>>> union of error messages and "codes" that we have individually
>>> used.
>>>
>> You've described the problem.
>>
>> Fred scatters his code with
>>
>> log_error(ERR_TOOMANYFILESOPEN);
>>
>> Bert does the same with
>>
>> fprintf_error(EC_FILECOUNTEXCEEDED, "Too many files open (%d)\n",
>> Nfiles);
>>
>> Now when we merge Fred's code with Bert's, what's going to happen?
>
> That's the wrong question, because the answer necessarily depends on the
> relationship between Fred and Bert. If they are independent third-party
> library developers, you're not likely to get them to use *your* error-
If they are truly independent (i.e., you are purchasing a COTS library),
then you *wrap* their library functions to map their error_t's to *your*
error scheme.
E.g.,
void *
MyMalloc(
size_t size,
error_t *error
) {
void *ptr;
if (size > MAX_ALLOCATION) {
MakeErrorCode(Err_TooBig,
"Allocation too large.",
"The requested piece of memory was larger than the
maximum supported for the process."
)
*error = Err_TooBig;
return NULL;
}
ptr = malloc(size);
if (ptr == NULL) {
MakeErrorCode(Err_NoMemory,
"Out of memory"
"The free memory pool has been exhausted."
)
*error = Err_NoMemory;
return NULL;
}
return ptr;
}
[Note that I am not trying to be "friendly" with my error messages
in this example. Also, the semantics for this example try to
resemble the semantics expected of traditional malloc. I would,
instead, return a "Result_t"]
> reporting system now. If they both work for you, then you can require
> them to use any system you want, and any sane system should work
> (although simpler systems may be more effort to scale up).
>
> In practice, the former case usually means that each set of third-party
> code has its own type for errors, and the functions you call them from
> will report errors upwards according to their own convention that need
> have nothing to do with the third-party code. But you're limited to the
> information that their API already provide.
Of course! Just as if you want to change the syntax of "decimal
strings" to prohibit leading (or TRAILING!) zeroes yet *mandate*
at least one character on each *side* of the decimal point, you
can't use strtod(3). Or, if you want to conditionally be able to
limit the range of values that can be represented by such
strings, etc.
[toc] | [prev] | [next] | [standalone]
| From | Don Y <this@isnotme.com> |
|---|---|
| Date | 2012-03-03 12:32 -0700 |
| Message-ID | <jitrk3$6mi$1@speranza.aioe.org> |
| In reply to | #18140 |
Hi Malcolm,
On 3/3/2012 4:45 AM, Malcolm McLean wrote:
> On Mar 3, 7:49 am, Don Y<t...@isnotme.com> wrote:
>>
>>> Centralised error systems mean that code will break if you try to move
>>> it to a different project.
>>
>> And, when our images are merged, we magically end up with the
>> union of error messages and "codes" that we have individually
>> used.
>
> You've described the problem.
>
> Fred scatters his code with
>
> log_error(ERR_TOOMANYFILESOPEN);
>
> Bert does the same with
>
> fprintf_error(EC_FILECOUNTEXCEEDED, "Too many files open (%d)\n",
> Nfiles);
>
> Now when we merge Fred's code with Bert's, what's going to happen?
If the same "underling" is signaling that count of files has been
exceeded, then that underling would have reported (to fred and
bert) in the manner that the underling has been documented.
E.g., (pseudocode)
error_t error;
if (!OpenFile(name_of_file, &error))
That line of code (or variant thereof) in bert and fred's code
would yield the same error code (and corresponding report) in
each case. I.e., "Too many files open. [The system can only
open 20 files for each user. Close some file(s).]".
(the bracketed portion being "extra clarification")
Bert and fred can embellish/replace this as appropriate to their
contexts/roles. E.g., bert might want to add "Too many photos
open. [A maximum of 9 photos can be examined at any given time.]"
The user sees the "too many photos open" and, if that is
sufficient for him to understand the nature of the problem,
fine. If he asks for more clarification, the "maximum of 9"
is offered up. If this still does not resolve the issue
("I'm only viewing 7 photos!"), more, lower level details
are exposed by revealing the details of the error reported
by OpenFile -- "20 files for each user". This suggests
that files are open elsewhere that aren't accounted for in
the "9 photos" context -- but that *are* known to lower
level OpenFile routine. Either a bug *or* the error is
being reported too low in the application -- perhaps this
layer should have been embelished by the layer *above*...
the one that called OpenPhoto()!
Meanwhile, fred might have opted to *replace* the error with
a unilateral proclamation: "Out of resources" with no further
reporting.
Note that this doesn't protect against fred writing his own
oPEN_fILE() routine and implementing whatever errors he wants
in it. So, *his* oPEN_fILE might return reports like:
"Golly, gee... I just can't keep track of all these files
you keep wanting to open!" :>
There is no way around this. Just like you can write your own
strtod() to parse a string for a numeric value instead of
relying on the one provided by the library. Fred can report
KB in units of 1,000 bytes while Bert can use 1,024.
But, if both fred and bert are aware of the ConvertToKB()
function's existence, then their notions of KB will be
consistent.
If they are both aware of the OpenFile() routine's existence,
then their error messages (from *that* layer) will be
consistent.
And, when BOTH fred and bert stop using OpenFile(), the
"Too many files open" error message will magically be excised
from the application -- along with the ERR_TOOMANYFILESOPEN
identifier.
I can't FORCE fred and bert to use OpenFile. I can't *force*
them to write good error messages. But, if I provide a
mechanism that makes presenting these messages to the user
easy and noticeably improves the quality of that experience,
they can exploit that mechanism easier than inventing an
ad hoc mechanism that they have to maintain for themselves
Corporate policy and peer pressure are the only real
policemen. All I can do is make a mechanism that *wants*
to be used, makes it easy to be used and that reduces the
chance of error creeping into that aspect of the code.
Alice joins the team and encounters:
MakeErrorCode(...)
and it doesn't take long for her to see how she can
exploit it to "explain" her code.
In regulated environments, this can go a long way to complying
with requirements for testing (has every error code been "touched"
during the execution of the test suite? just instrument the
routine that resolves error codes and tally each unique code
that is presented to it!), elimination of dead code, etc.
[toc] | [prev] | [next] | [standalone]
| From | Don Y <this@isnotme.com> |
|---|---|
| Date | 2012-03-03 15:04 -0700 |
| Message-ID | <jiu4hi$u1n$1@speranza.aioe.org> |
| In reply to | #18135 |
Hi Stefan,
On 3/3/2012 8:41 AM, Stefan Ram wrote:
> Don Y<this@isnotme.com> writes:
>> I.e., "Your address book is full. Delete one or more entries
>> of you want to add this new contact" vs. "Image too large to
>> print. Try a lower resolution or size." Putting the "out of
>> memory" error into context adds value to the user (and thus
>> the product).
>
> Most C-program processes do not create such nice error
> messages when the memory for objects with automatic storage
> duration is exhausted. Sometimes, they just die
> ungracefully.
Sure. But you're surely not advocating the continuation of
that practice? "Just SIGSEGV and let the user figure out
what's wrong. Don't even bother checking malloc's return value!"
<grin>
Most programs (esp desktop/mainframe) operate on the assumption
that they will have what they need -- often without ever THINKING
about what they actually need! ("We'll cross that bridge when we
come to it"). Few actively consider how they will react to
these conditions when/if they are encountered.
"Ooops!"
> Saying that the address book was full, when in fact there is
> no memory with dynamic storage duration available anymore,
> might mislead the user into believing that the specific
> memory of his address book was full when in fact the
> general dynamic memory is exhausted, which means that now
> all of his "books" suddenly are full. It might make him
> beliefe the false idea that there is a fixed number of
> entries reserved for his address book, which now is reached.
Drilling down (to the error reported by malloc itself) exposes
that detail to the user.
In my case, the database presents remedies to each "error"
so the user is advised on the course of action he should/could
follow. That's the point of being able to give very specific
information to the "user" -- so he can best utilize the
software to achieve *his* goals.
E.g., if "system memory" is exhausted, he can learn that he
can remedy this by freeing up memory *anywhere* (within reason).
I.e., he can trade an MP3 file for one or more address book entries.
OTOH, if the address book has fixed size structures that impose
a limit on the number of entries, a more appropriate remedy would
be "delete one or more address book entries before trying to add"
Malloc() doesn't need to know about these remedies. It doesn't
know *where* it will be used nor *how*. The context appropriate
for reporting the error to the user is the context that offers
explanations and remedies to the user (note that this context
can change as the user drills down)
> If the lack of dynamic memory of the C-program process is a
> lack of system memory, something less destructive, such as
> just closing an unused window, might be more appropriate as
> a counter measure than deleting precious address-book entries.
>
> Usually most users will get a better, more correct idea of
> the state of things from "Out of memory" than from "Address
> book full" in the case that the process encounters a null
> result from malloc.
You can't make assumptions about the skill level of your user
(well, you *can* but then you implicitly restrict your user
base). You want to be able to offer as much detail to the
user as the application considers appropriate for the types
of users it expects to interact with.
E.g., I see a SIGSEGV and I know what the problem is. If it
was also tagged with a __FILE__ __LINE__, then I would also
know *where* it is!
OTOH, your grandmother's eyes would cross if she saw the
same "report".
[toc] | [prev] | [next] | [standalone]
| From | Ian Collins <ian-news@hotmail.com> |
|---|---|
| Date | 2012-03-04 11:09 +1300 |
| Message-ID | <9rfj4aFtd8U4@mid.individual.net> |
| In reply to | #18169 |
On 03/ 4/12 11:04 AM, Don Y wrote: > Hi Stefan, > > On 3/3/2012 8:41 AM, Stefan Ram wrote: >> Don Y<this@isnotme.com> writes: >>> I.e., "Your address book is full. Delete one or more entries >>> of you want to add this new contact" vs. "Image too large to >>> print. Try a lower resolution or size." Putting the "out of >>> memory" error into context adds value to the user (and thus >>> the product). >> >> Most C-program processes do not create such nice error >> messages when the memory for objects with automatic storage >> duration is exhausted. Sometimes, they just die >> ungracefully. > > Sure. But you're surely not advocating the continuation of > that practice? "Just SIGSEGV and let the user figure out > what's wrong. Don't even bother checking malloc's return value!" > <grin> There is nothing a program can do if the memory for objects with automatic storage duration is exhausted. -- Ian Collins
[toc] | [prev] | [next] | [standalone]
| From | Don Y <this@isnotme.com> |
|---|---|
| Date | 2012-03-03 16:55 -0700 |
| Message-ID | <jiub2d$e64$1@speranza.aioe.org> |
| In reply to | #18170 |
Hi Ian, On 3/3/2012 3:09 PM, Ian Collins wrote: > On 03/ 4/12 11:04 AM, Don Y wrote: >> On 3/3/2012 8:41 AM, Stefan Ram wrote: >>> Don Y<this@isnotme.com> writes: >>>> I.e., "Your address book is full. Delete one or more entries >>>> of you want to add this new contact" vs. "Image too large to >>>> print. Try a lower resolution or size." Putting the "out of >>>> memory" error into context adds value to the user (and thus >>>> the product). >>> >>> Most C-program processes do not create such nice error >>> messages when the memory for objects with automatic storage >>> duration is exhausted. Sometimes, they just die >>> ungracefully. >> >> Sure. But you're surely not advocating the continuation of >> that practice? "Just SIGSEGV and let the user figure out >> what's wrong. Don't even bother checking malloc's return value!" >> <grin> > > There is nothing a program can do if the memory for objects with > automatic storage duration is exhausted. In a general sense, no. But, in my case, the program can choose to handle a signal delivered by the OS when it exhausts this resource. It can then request its stack to be increased and resume execution. Or, *it* can inform the user of this problem and die GRACEFULLY. Or, it can let the OS's default behavior KILL the process.
[toc] | [prev] | [next] | [standalone]
| From | Ian Collins <ian-news@hotmail.com> |
|---|---|
| Date | 2012-03-04 13:04 +1300 |
| Message-ID | <9rfps3Ftd8U5@mid.individual.net> |
| In reply to | #18175 |
On 03/ 4/12 12:55 PM, Don Y wrote: > Hi Ian, > > On 3/3/2012 3:09 PM, Ian Collins wrote: >> On 03/ 4/12 11:04 AM, Don Y wrote: >>> On 3/3/2012 8:41 AM, Stefan Ram wrote: >>>> Don Y<this@isnotme.com> writes: >>>>> I.e., "Your address book is full. Delete one or more entries >>>>> of you want to add this new contact" vs. "Image too large to >>>>> print. Try a lower resolution or size." Putting the "out of >>>>> memory" error into context adds value to the user (and thus >>>>> the product). >>>> >>>> Most C-program processes do not create such nice error >>>> messages when the memory for objects with automatic storage >>>> duration is exhausted. Sometimes, they just die >>>> ungracefully. >>> >>> Sure. But you're surely not advocating the continuation of >>> that practice? "Just SIGSEGV and let the user figure out >>> what's wrong. Don't even bother checking malloc's return value!" >>> <grin> >> >> There is nothing a program can do if the memory for objects with >> automatic storage duration is exhausted. > > In a general sense, no. But, in my case, the program can choose > to handle a signal delivered by the OS when it exhausts this > resource. It can then request its stack to be increased and > resume execution. What if the OS is unwilling or unable to do this? Process limits aren't usually something a user process can increase. -- Ian Collins
[toc] | [prev] | [next] | [standalone]
| From | Don Y <this@isnotme.com> |
|---|---|
| Date | 2012-03-03 18:24 -0700 |
| Message-ID | <jiug8r$odo$1@speranza.aioe.org> |
| In reply to | #18176 |
Hi Ian,
On 3/3/2012 5:04 PM, Ian Collins wrote:
>>>>> Most C-program processes do not create such nice error
>>>>> messages when the memory for objects with automatic storage
>>>>> duration is exhausted. Sometimes, they just die
>>>>> ungracefully.
>>>>
>>>> Sure. But you're surely not advocating the continuation of
>>>> that practice? "Just SIGSEGV and let the user figure out
>>>> what's wrong. Don't even bother checking malloc's return value!"
>>>> <grin>
>>>
>>> There is nothing a program can do if the memory for objects with
>>> automatic storage duration is exhausted.
>>
>> In a general sense, no. But, in my case, the program can choose
>> to handle a signal delivered by the OS when it exhausts this
>> resource. It can then request its stack to be increased and
>> resume execution.
>
> What if the OS is unwilling or unable to do this? Process limits aren't
> usually something a user process can increase.
(sigh) I'd really rather not get into this "distraction", but...
The simple answer to your question is: then the process
(which might be all or part of an "application") can either
die gracefully, die ungracefully, or blindly trudge along
expecting the OS to take a hatchet to it at some point
(if you've already tried to *use* those resources that don't
yet exist -- i.e., and trapped to the OS on a page fault -- then
that hatchet job will be "real soon now" :> )
The longer answer has to address more issues. :(
A process (well, technically, an executing THREAD within a
process) can ask for resources (various flavors of memory be
some of those) at any time. The OS can choose to grant,
deny or *defer* that request.
A process (same caveat as above) can also *implicitly*
request additional resources. E.g., if it has been configured
with a "stack allocation" of 20KB but only 10K have been
actualized, a page fault in the stack segment can cause the
OS to provide the underlying physical memory without the
"process" knowing this has happened.
[of course, a process watching a system timer might wonder
why that last instruction took 100us to execute! :> If
this sort of behavior is not acceptable -- e.g., if the
process has timeliness constraints -- then the configuration
could be modified to instantiate all of the stack allocation
at startup. Faults thereafter would have to be *negotiated*
with the OS!]
A "smart" application would review its past behavior and
anticipate its needs -- requesting those resources at
the start of execution (instead of taking multiple hits
each time it "needs a little more"). This can also
provide more immediate feedback to the user of resource
shortages before the application STUMBLES onto that
limit (e.g., chugging along, trapping 9 times, getting
an extra 1K each time -- and continuing -- until eventually
discovering that the 10th -- and final -- trap's request
won't be satisfied! "Why didn't you tell me that before
I got started?" "Because you didn't ASK!" :> )
A *really* smart application would scrutinize its actual
workload and adjust its resource requests to best fit
the actual needs of that workload. I.e., aiming for
the sky when you only need "a little more" is likely
to leave your request unsatisfied.
The last aspect is the *transience* of those resources.
A process can *lose* resources while it is executing.
This can be implicit or explicit (without or with formal
notification).
E.g., as stack penetration decreases, the OS can silently
choose to recover that memory from the process (anything
"past" the current stack pointer is "undefined"!).
Similarly, the OS can reclaim portions of the TEXT segment.
[of course, these can be configured per the minimum
stack allocation for the same reasons outlined before]
The OS can also (asynchronously) *ask* a process to free
up resources -- voluntarily. The process can choose to
comply -- or not.
This allows a process to be designed to exploit resources
when they are available -- without penalizing other processes
that want to co-execute (since it has no knowledge of when
or if those processes might come along!). A cooperative
process will free up as much as it can as soon as it can.
So, if the process has been using those resources to
*anticipate* future needs or speed up responses (e.g.,
precalculating lots of options in anticipation of the
user asking for one or more of them), it can <shrug> and
give up those hopeful gains -- and resort to a leaner
implementation.
A process can also be *told* to release resources (on pain
of death :> ). So, an uncooperative process ("I asked you,
nicely, to free up some memory and you thumbed your nose at
me!") can't benefit from this antisocial behavior.
If the process truly can't operate without those resources,
"Sorry, Charlie!". (the OS said it NEEDS them. If you
can't provide them, the OS will HAVE TO take them from
somewhere. That could very well be *you*! The consequences
of this can vary -- but, in any case, *you* won't have
control over them!)
(deep breath)
In concert, the two mechanisms let the "system" dynamically
reapportion resources to fit the needs and priorities of
the processes/applications running on it.
E.g., if X requests more of a resource, the OS can choose
to grant it, if a surplus is available; *or*, can approach
other "consumers" looking for a "hand-out". Worst case,
it can kill consumers to make those resources available.
Or not.
The application writer can ignore all of these mechanisms
and just live with the default behavior. But, that means
the application is less capable and more brittle: "You
give me no options OTHER THAN to terminate you..."
As I said, I would really rather this not turn into another
"distraction"... :-/
[toc] | [prev] | [next] | [standalone]
| From | Malcolm McLean <malcolm.mclean5@btinternet.com> |
|---|---|
| Date | 2012-03-03 14:30 -0800 |
| Message-ID | <f76bcd7f-15ec-4a20-b2b0-736cb81d0c10@k4g2000yqa.googlegroups.com> |
| In reply to | #18169 |
On Mar 3, 10:04 pm, Don Y <t...@isnotme.com> wrote: > > You can't make assumptions about the skill level of your user > (well, you *can* but then you implicitly restrict your user > base). You want to be able to offer as much detail to the > user as the application considers appropriate for the types > of users it expects to interact with. > Normally you've got at least three audiences for an error report. The user usually has no interest in the program other than as a tool to get his work done, but he wants some response other than the program simply failing to work as expected. The first line technical support person needs to know if a problem is on his list of known issues, and the programmers need to know in which routine the program failed and, ideally, what data it was operating on at the time.
[toc] | [prev] | [next] | [standalone]
| From | Don Y <this@isnotme.com> |
|---|---|
| Date | 2012-03-03 17:06 -0700 |
| Message-ID | <jiubmb$fem$1@speranza.aioe.org> |
| In reply to | #18171 |
Hi Malcolm,
On 3/3/2012 3:30 PM, Malcolm McLean wrote:
> On Mar 3, 10:04 pm, Don Y<t...@isnotme.com> wrote:
>>
>> You can't make assumptions about the skill level of your user
>> (well, you *can* but then you implicitly restrict your user
>> base). You want to be able to offer as much detail to the
>> user as the application considers appropriate for the types
>> of users it expects to interact with.
>>
> Normally you've got at least three audiences for an error report. The
Yes. -----------------^^^^^^^^
> user usually has no interest in the program other than as a tool to
> get his work done, but he wants some response other than the program
> simply failing to work as expected.
Given that the first response most users take to an error is to
REPEAT THE SAME ACTION (hoping for different results :> ), you
now have a user who has made the same mistake TWICE. Chances
are, his level of anxiety is already elevated. Giving him the
same error message is a foolish response to this second attempt.
You should automatically begin embellishment.
if the user KNEW he had made an error in the first case, he would
retry WITH GREATER CARE in the second attempt and the error would
not manifest. OTOH, if he doesn't understand what he did wrong
and repeats the same actions -- only to be met with the same
UNINFORMATIVE REPORT (hey, if it was informative, he would now
KNOW what was wrong with his first attempt and wouldn't be
retrying it!) -- *you* are the problem.
"OK, so I typed a 'bad value'. What the hell is WRONG WITH IT???!"
> The first line technical support
> person needs to know if a problem is on his list of known issues, and
Or, how to interpret the error message for the user. *Effective*
help desk staff make note of what problems users have with a
product/program and convey that information back to the development
staff. Sometimes, the language is defective/insufficient. Or,
the process is unintuitive ("Why do I have to enter my SSN before
I *can* enter my name?").
> the programmers need to know in which routine the program failed and,
> ideally, what data it was operating on at the time.
Yes. Being able to report where EXACTLY in the code the 'reporting
condition' was detected goes a long way to expediting resolution
of the problem.
"The malloc() on line 27 of file foo.c returned NULL. I know
this because the error was reported in the conditional on line 28!"
Time for my afternoon walk before it gets much cooler...
[toc] | [prev] | [next] | [standalone]
| From | Ian Collins <ian-news@hotmail.com> |
|---|---|
| Date | 2012-03-05 10:09 +1300 |
| Message-ID | <9ri412FadbU2@mid.individual.net> |
| In reply to | #18090 |
On 03/ 2/12 08:48 AM, Don Y wrote: > Hi, > > [Please take the time to understand what I'm looking for before > replying. I've spent a lot of time describing it; it would > be courteous for you to make a similar investment before > commenting on it.] [I think I have!] > I have a suite of projects that utilize a common approach to > error reporting. Instead of a PASS/FAIL result, most functions > return information regarding the nature of the "failure" (which > can also include "partial failures"... "warnings"). These > reports allow upper levels of the application to convey those > details to the user without exposing all of the *mechanism* > involved to those upper levels. My usual technique for this class of problem is to build the tables in a programmer and machine friendly format, typically XML in the guise of an Open Office document. The programmer(s) can easily maintain and version control the document and the machine can easily perform validation of the data (one of my teams developed an XML schema validation tool for this purpose: http://sut.sourceforge.net) and generate the necessary headers. <snip> > > A "solution" also needs to address the problem of *explaining* > the "result" (to the ultimate user). The point at which the > result is "signaled" contains the most information about the > nature of the "problem" being reported though it is in a > very narrowly defined context: i.e., you can tell the user > "Multiple decimal points encountered" -- though you can't > indicate the role that the value being entered plays in the > application (is this a person's wages? the weight of a > newborn child? the average lifespan of a male tortoise?). Tales in an Office document are ideal for this. You can include as much information is you want, Your code generation can select various subsets of the data to present as user messages. -- Ian Collins
[toc] | [prev] | [next] | [standalone]
| From | Don Y <this@isnotme.com> |
|---|---|
| Date | 2012-03-04 16:03 -0700 |
| Message-ID | <jj0scq$ckd$1@speranza.aioe.org> |
| In reply to | #18206 |
Hi Ian, On 3/4/2012 2:09 PM, Ian Collins wrote: > On 03/ 2/12 08:48 AM, Don Y wrote: >> I have a suite of projects that utilize a common approach to >> error reporting. Instead of a PASS/FAIL result, most functions >> return information regarding the nature of the "failure" (which >> can also include "partial failures"... "warnings"). These >> reports allow upper levels of the application to convey those >> details to the user without exposing all of the *mechanism* >> involved to those upper levels. > > My usual technique for this class of problem is to build the tables in a > programmer and machine friendly format, typically XML in the guise of an > Open Office document. > > The programmer(s) can easily maintain and version control the document > and the machine can easily perform validation of the data (one of my > teams developed an XML schema validation tool for this purpose: > http://sut.sourceforge.net) and generate the necessary headers. Yes, but now you have to manually relate the messages to the code from which they were "reasoned". It would be like keeping the *comments* for your source code in a MSWord document (i.e., sure, you could *do* it but you KNOW the two documents will quickly get out of sync as pressure has you updating one and defering the effort of updating the other). E.g., the approach I am taking here is analagous to how Literate Programming couples documentation with source code (except I am only tackling the "error reporting" aspect of the task). > <snip> >> >> A "solution" also needs to address the problem of *explaining* >> the "result" (to the ultimate user). The point at which the >> result is "signaled" contains the most information about the >> nature of the "problem" being reported though it is in a >> very narrowly defined context: i.e., you can tell the user >> "Multiple decimal points encountered" -- though you can't >> indicate the role that the value being entered plays in the >> application (is this a person's wages? the weight of a >> newborn child? the average lifespan of a male tortoise?). > > Tales s/Tales/Tables/ ? > in an Office document are ideal for this. You can include as much > information is you want, Your code generation can select various subsets > of the data to present as user messages. I extract the error code, short message and long message (as well as the locale indicator) and stuff those into a (real) database (you could just as easily create a big array of struct's and index/search that based on the "(error code, locale)" presented). This moves all that "text" out of the "TEXT" section of the program (it could reside on a different *processor*!). It also lets someone non-technical make and review translations without having to understand the actual code surrounding it (though the code acts as the final arbiter of what the error message actually *should* convey).
[toc] | [prev] | [next] | [standalone]
| From | Ian Collins <ian-news@hotmail.com> |
|---|---|
| Date | 2012-03-05 13:26 +1300 |
| Message-ID | <9rifh9FadbU5@mid.individual.net> |
| In reply to | #18211 |
On 03/ 5/12 12:03 PM, Don Y wrote: > Hi Ian, > > On 3/4/2012 2:09 PM, Ian Collins wrote: >> On 03/ 2/12 08:48 AM, Don Y wrote: > >>> I have a suite of projects that utilize a common approach to >>> error reporting. Instead of a PASS/FAIL result, most functions >>> return information regarding the nature of the "failure" (which >>> can also include "partial failures"... "warnings"). These >>> reports allow upper levels of the application to convey those >>> details to the user without exposing all of the *mechanism* >>> involved to those upper levels. >> >> My usual technique for this class of problem is to build the tables in a >> programmer and machine friendly format, typically XML in the guise of an >> Open Office document. >> >> The programmer(s) can easily maintain and version control the document >> and the machine can easily perform validation of the data (one of my >> teams developed an XML schema validation tool for this purpose: >> http://sut.sourceforge.net) and generate the necessary headers. > > Yes, but now you have to manually relate the messages to the > code from which they were "reasoned". It would be like keeping > the *comments* for your source code in a MSWord document (i.e., > sure, you could *do* it but you KNOW the two documents will > quickly get out of sync as pressure has you updating one and > defering the effort of updating the other). Not at all. First the user or log messages have to be documented somewhere, for user documentation and testing. Scattering them throughout the code isn't a great way to do that. Second, the document is the *source* for the messages and error codes, so it will always be up to date. > E.g., the approach I am taking here is analagous to how Literate > Programming couples documentation with source code (except I am > only tackling the "error reporting" aspect of the task). In my case, the documentation *is* part of the source code. >>> >>> A "solution" also needs to address the problem of *explaining* >>> the "result" (to the ultimate user). The point at which the >>> result is "signaled" contains the most information about the >>> nature of the "problem" being reported though it is in a >>> very narrowly defined context: i.e., you can tell the user >>> "Multiple decimal points encountered" -- though you can't >>> indicate the role that the value being entered plays in the >>> application (is this a person's wages? the weight of a >>> newborn child? the average lifespan of a male tortoise?). >> >> Tales > > s/Tales/Tables/ ? :) >> in an Office document are ideal for this. You can include as much >> information is you want, Your code generation can select various subsets >> of the data to present as user messages. > > I extract the error code, short message and long message (as well as > the locale indicator) and stuff those into a (real) database > (you could just as easily create a big array of struct's and > index/search that based on the "(error code, locale)" presented). > > This moves all that "text" out of the "TEXT" section of the program > (it could reside on a different *processor*!). It also lets someone > non-technical make and review translations without having to understand > the actual code surrounding it (though the code acts as the final > arbiter of what the error message actually *should* convey). Our approaches appear to be opposite. You extract messages from the code, I inject them into the code (and the tests and user documentation). -- Ian Collins
[toc] | [prev] | [next] | [standalone]
| From | Don Y <this@isnotme.com> |
|---|---|
| Date | 2012-03-04 22:21 -0700 |
| Message-ID | <jj1igi$oae$1@speranza.aioe.org> |
| In reply to | #18215 |
Hi Ian, On 3/4/2012 5:26 PM, Ian Collins wrote: >>>> I have a suite of projects that utilize a common approach to >>>> error reporting. Instead of a PASS/FAIL result, most functions >>>> return information regarding the nature of the "failure" (which >>>> can also include "partial failures"... "warnings"). These >>>> reports allow upper levels of the application to convey those >>>> details to the user without exposing all of the *mechanism* >>>> involved to those upper levels. >>> >>> My usual technique for this class of problem is to build the tables in a >>> programmer and machine friendly format, typically XML in the guise of an >>> Open Office document. >>> >>> The programmer(s) can easily maintain and version control the document >>> and the machine can easily perform validation of the data (one of my >>> teams developed an XML schema validation tool for this purpose: >>> http://sut.sourceforge.net) and generate the necessary headers. >> >> Yes, but now you have to manually relate the messages to the >> code from which they were "reasoned". It would be like keeping >> the *comments* for your source code in a MSWord document (i.e., >> sure, you could *do* it but you KNOW the two documents will >> quickly get out of sync as pressure has you updating one and >> defering the effort of updating the other). > > Not at all. > > First the user or log messages have to be documented somewhere, for user > documentation and testing. Yes. I document them IN THE CODE. > Scattering them throughout the code isn't a > great way to do that. Why? It ensures EVERY error code is documented. And, it keeps that proximate to the actual code itself. *This* is what the code is testing for... not something else that you THINK it is enforcing! > Second, the document is the *source* for the messages and error codes, > so it will always be up to date. What happens when an error code is never referenced? How does your document ELIDE that error code and its documentation? >> E.g., the approach I am taking here is analagous to how Literate >> Programming couples documentation with source code (except I am >> only tackling the "error reporting" aspect of the task). > > In my case, the documentation *is* part of the source code. Fair enough. You should look at Literate Programming for a different take on this (see URL later) >>>> A "solution" also needs to address the problem of *explaining* >>>> the "result" (to the ultimate user). The point at which the >>>> result is "signaled" contains the most information about the >>>> nature of the "problem" being reported though it is in a >>>> very narrowly defined context: i.e., you can tell the user >>>> "Multiple decimal points encountered" -- though you can't >>>> indicate the role that the value being entered plays in the >>>> application (is this a person's wages? the weight of a >>>> newborn child? the average lifespan of a male tortoise?). >>> >>> Tales >> >> s/Tales/Tables/ ? > > :) <grin> I stared at that for a LONG time trying to figure out what MS had come up with (I don't use Office). Finally slapped my head (d'uh!) to realize it had to be a typo! :> >>> in an Office document are ideal for this. You can include as much >>> information is you want, Your code generation can select various subsets >>> of the data to present as user messages. >> >> I extract the error code, short message and long message (as well as >> the locale indicator) and stuff those into a (real) database >> (you could just as easily create a big array of struct's and >> index/search that based on the "(error code, locale)" presented). >> >> This moves all that "text" out of the "TEXT" section of the program >> (it could reside on a different *processor*!). It also lets someone >> non-technical make and review translations without having to understand >> the actual code surrounding it (though the code acts as the final >> arbiter of what the error message actually *should* convey). > > Our approaches appear to be opposite. You extract messages from the > code, I inject them into the code (and the tests and user documentation). Fair enough. My approach is "inspired" by Literate Programming (http://en.wikipedia.org/wiki/Literate_programming). In either approach, you need to have a tool/utility massage a file (or files) to generate the actual "source" and supporting files. I bundle it in the source because I can just let MakeErrorCode be a macro that doesn't alter the source (Literate Programming requires the source to be "extracted" -- "tangled").
[toc] | [prev] | [next] | [standalone]
| From | Ian Collins <ian-news@hotmail.com> |
|---|---|
| Date | 2012-03-05 20:46 +1300 |
| Message-ID | <9rj9aoFi9oU1@mid.individual.net> |
| In reply to | #18217 |
On 03/ 5/12 06:21 PM, Don Y wrote: > Hi Ian, > > On 3/4/2012 5:26 PM, Ian Collins wrote: > >>>>> I have a suite of projects that utilize a common approach to >>>>> error reporting. Instead of a PASS/FAIL result, most functions >>>>> return information regarding the nature of the "failure" (which >>>>> can also include "partial failures"... "warnings"). These >>>>> reports allow upper levels of the application to convey those >>>>> details to the user without exposing all of the *mechanism* >>>>> involved to those upper levels. >>>> >>>> My usual technique for this class of problem is to build the tables in a >>>> programmer and machine friendly format, typically XML in the guise of an >>>> Open Office document. >>>> >>>> The programmer(s) can easily maintain and version control the document >>>> and the machine can easily perform validation of the data (one of my >>>> teams developed an XML schema validation tool for this purpose: >>>> http://sut.sourceforge.net) and generate the necessary headers. >>> >>> Yes, but now you have to manually relate the messages to the >>> code from which they were "reasoned". It would be like keeping >>> the *comments* for your source code in a MSWord document (i.e., >>> sure, you could *do* it but you KNOW the two documents will >>> quickly get out of sync as pressure has you updating one and >>> defering the effort of updating the other). >> >> Not at all. >> >> First the user or log messages have to be documented somewhere, for user >> documentation and testing. > > Yes. I document them IN THE CODE. > >> Scattering them throughout the code isn't a >> great way to do that. > > Why? Because it is easier to generate code than it is to parse code and extract information from an entire code base. It is also easier to maintain a single document in a form that can be translated in to things other than code (especially if you have a need to get some of the messages translated). > It ensures EVERY error code is documented. And, it keeps that > proximate to the actual code itself. *This* is what the code is > testing for... not something else that you THINK it is enforcing! Quite. The table of error codes/messages/whatever is all generated from one place. If a new error code is required , it has to be added to the master file. >> Second, the document is the *source* for the messages and error codes, >> so it will always be up to date. > > What happens when an error code is never referenced? How does > your document ELIDE that error code and its documentation? Nothing. How many of the error codes in a typical system header (such as <errno.h> on a Unix system) does any one application actually use? If new errors are added to the master file as required, this will not really be a problem. >>> E.g., the approach I am taking here is analagous to how Literate >>> Programming couples documentation with source code (except I am >>> only tackling the "error reporting" aspect of the task). >> >> In my case, the documentation *is* part of the source code. > > Fair enough. You should look at Literate Programming for a > different take on this (see URL later) We did, however code editors tend to be piss poor word processors and word processors tend to be piss poor text editors! It's quite easy to write code in Open Office and extract the code sections for compilation, but it's a process not well suited to contemporary tools (IDEs). On the project I mentioned, the master XML was used to generate many different components, including database tables and their equivalent C structures and enumerations. So this file had a lot more value than it would had it simply been used for error codes and messages. Elsewhere in this thread someone mentioned a function to check input values, well the types and range of common data types were also specified in this file, so all the range checking and error reporting was centralised. >>>>> A "solution" also needs to address the problem of *explaining* >>>>> the "result" (to the ultimate user). The point at which the >>>>> result is "signaled" contains the most information about the >>>>> nature of the "problem" being reported though it is in a >>>>> very narrowly defined context: i.e., you can tell the user >>>>> "Multiple decimal points encountered" -- though you can't >>>>> indicate the role that the value being entered plays in the >>>>> application (is this a person's wages? the weight of a >>>>> newborn child? the average lifespan of a male tortoise?). > >>>> Tables in an Office document are ideal for this. You can include as much >>>> information is you want, Your code generation can select various subsets >>>> of the data to present as user messages. >>> >>> I extract the error code, short message and long message (as well as >>> the locale indicator) and stuff those into a (real) database >>> (you could just as easily create a big array of struct's and >>> index/search that based on the "(error code, locale)" presented). >>> >>> This moves all that "text" out of the "TEXT" section of the program >>> (it could reside on a different *processor*!). It also lets someone >>> non-technical make and review translations without having to understand >>> the actual code surrounding it (though the code acts as the final >>> arbiter of what the error message actually *should* convey). >> >> Our approaches appear to be opposite. You extract messages from the >> code, I inject them into the code (and the tests and user documentation). > > Fair enough. My approach is "inspired" by Literate Programming > (http://en.wikipedia.org/wiki/Literate_programming). In either > approach, you need to have a tool/utility massage a file (or > files) to generate the actual "source" and supporting files. I believe the the tools required to generate code from XML are much simpler than those required to extract documentation form code (other than from code comments). > I bundle it in the source because I can just let MakeErrorCode > be a macro that doesn't alter the source (Literate Programming > requires the source to be "extracted" -- "tangled"). But it doesn't solve the uniqueness problem. With a master file, you don't have to worry, or even define the error values. The translator can do that for you. -- Ian Collins
[toc] | [prev] | [next] | [standalone]
Page 4 of 5 — ← Prev page 1 2 3 [4] 5 Next page →
Back to top | Article view | comp.lang.c
csiph-web