473,216 Members | 1,277 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,216 software developers and data experts.

A general error handling facility

Microsoft proposed recently (In the Technical Report 24173 presented to
the Standards Comitee) a change in the C library in the sense of more
security.

Basically, missing size information is passed to the new primitives like
strcat_s(), gets_s(), and many others.

The good thing in this proposal is that the specifications of the new
library are much more precise than in the existing library, an
improvement that made me start implementing it within the framework of
lcc-win32.

One of the most interesting features of that library is the proposal of
a mechanism for testing the requirements of a function, and the calling
of a routine that the user can modify when a requirement for a function
is missing.

This is a much more attenuated form of the "Programming by contract"
proposed by Betrand Meyer in his Eiffel language. A function call is
seen as a contract within two parties: the calling function, that must
furnish correct arguments to the called function, and the called
function that must furnish specific results to the caller.

In the proposal (I will call it TR 24731 for short) the requirements
of each function are specified in great detail. Let's take, for instance
the function

errno_t strncpy_s(char * restrict s1,
rsize_t s1max,
const char * restrict s2,
rsize_t n);

This function has the following runtime constraints:

1) Neither s1 nor s2 shall be a null pointer.
2) Neither s1max nor n shall be greater than RSIZE_MAX.
3) s1max shall not equal zero.
4) If n is not less than s1max, then s1max shall be greater than
strnlen_s(s2, s1max).
5) Copying shall not take place between objects that overlap.

A simple implementation of this function could be like this:

errno_t strncpy_s(char * restrict DestinationString,
rsize_t DestinationLength,
const char * restrict SourceString,
rsize_t n )
{
errno_t rc = -1;

// strnlen_s is safe to use as it has no rt constraints
rsize_t srcLen = strnlen_s( SourceString, DestinationLength );

// Verify runtime-constraints
if (require( DestinationString != NULL) &&
require(SourceString != NULL) &&
require( DestinationLength <= RSIZE_MAX) &&
require( n <= RSIZE_MAX) &&
((n < DestinationLength) ||
require( srcLen <= DestinationLength-1 )) &&
__check_overlap(DestinationString, DestinationLength,
SourceString, srcLen )) {

for( ; n; --n) {
if( *SourceString == 0 )
break;
*DestinationString++ = *SourceString++;
}
*DestinationString = 0;
rc = 0;
} else {
// Runtime-constraints found, store zero in receiving field
if( (DestinationString != NULL) && DestinationLength 0 &&
DestinationLength <= RSIZE_MAX ) {
DestinationString[0] = 0;
}
}
return( rc );
}

I have defined the require macro as follows:

#define require(constraint) \
((constraint) ? 1 : ConstraintFailed(__func__,#constraint,NULL) )

Note that this must be a macro since it uses the __func__ identifier,
that is the name of the current function being compiled, in the example
the function strncpy_s.

The "ConstraintFailed" function is defined like this:

#define MSG_MAX 512
int ConstraintFailed( const char *fn, const char *reason,
void *reserved )
{
constraint_handler_t handlerFn = get_constraint_handler_s();
char msg[MSG_MAX];

snprintf(msg,sizeof(msg),
"In function %s, assertion\n%s\nfailed\n",
fn,reason);
handlerFn(msg,reserved,EINVAL);
return 0;
}

The ConstraintFailed function gets the current active handler and calls
it. If the handler returns, it returns zero, what makes the whole series
of tests separated by the && construct fail.

Note that this function will be called only once for the first
constraint that failed, as specified in TR 24731.

What would be interesting is to generalize this mechanism to be able to
use it in other contexts and within other libraries. Obviously this is
not a replacement for try/catch (what lcc-win32 already offers) but it
is *much* better than nothing, as now.

Note that the constraint handlers are set per thread within the context
of lcc-win32 even if this is not specified in the Microsoft proposal.
(You know the tune: "embrace and extend" :-)

Since the handler function can be changed with the function
set_constraint_handler(), you can modify the handler to just log the
errors instead of aborting the program, mailing you an error report
if it detects an internet connection, or whatever.

True, you can say that the assert macro is already there, but it doesn't
have the possibility of dynamically changing the handler according to
the importance of the failure, like this one has.

Comments welcome.

jacob
Jul 6 '06 #1
7 1998
jacob navia wrote:

[long explanation snipped]
>
Since the handler function can be changed with the function
set_constraint_handler(), you can modify the handler to just log the
errors instead of aborting the program, mailing you an error report
if it detects an internet connection, or whatever.

True, you can say that the assert macro is already there, but it doesn't
have the possibility of dynamically changing the handler according to
the importance of the failure, like this one has.

Comments welcome.
Isn't this all rather dangerous?

If a function's contract lists a number of constraints, the function can
be coded assuming these are honoured and can can enforce this though assert.

If you are going to add an option to report rather than abort, you are
opening up a vast can of UB worms - what does the function do if any of
its constraints are violated?

--
Ian Collins.
Jul 6 '06 #2
Ian Collins a écrit :
>
Isn't this all rather dangerous?

If a function's contract lists a number of constraints, the function can
be coded assuming these are honoured and can can enforce this though assert.

If you are going to add an option to report rather than abort, you are
opening up a vast can of UB worms - what does the function do if any of
its constraints are violated?
Well, if you see the design of strncpy_s in my post you will see
that all constraints are grouped in an if statement.

The else part follows the specifications when the constraints are
NOT there, i.e. what now runs under "unspecified behavior" *IS*
specified, as you can see.

Other functions may have different specs, but in most cases a
meaningful behavior under error is possible. Note that this
happens only if the handler function does NOT abort or make
a long jump out of that context in a pre-established recovery
context...

jacob
Jul 7 '06 #3
jacob navia wrote:
Ian Collins a écrit :
>>
Isn't this all rather dangerous?

If a function's contract lists a number of constraints, the function can
be coded assuming these are honoured and can can enforce this though
assert.

If you are going to add an option to report rather than abort, you are
opening up a vast can of UB worms - what does the function do if any of
its constraints are violated?

Well, if you see the design of strncpy_s in my post you will see
that all constraints are grouped in an if statement.

The else part follows the specifications when the constraints are
NOT there, i.e. what now runs under "unspecified behavior" *IS*
specified, as you can see.

Other functions may have different specs, but in most cases a
meaningful behavior under error is possible. Note that this
happens only if the handler function does NOT abort or make
a long jump out of that context in a pre-established recovery
context...
Then how do you differentiate between a constraint than can and one that
can't be violated?

In C++ we'd use a mix of asserts and exceptions to do this, but C lacks
this feature, so how would you report a constraint violation to the
caller without some form of asynchronous callback?

In the cases where meaningful behaviour under error is possible, I'd
have thought this behaviour would involve some form of notification to
the caller.

--
Ian Collins.
Jul 7 '06 #4
Ian Collins a écrit :
jacob navia wrote:
>>Ian Collins a écrit :

>>>Isn't this all rather dangerous?

If a function's contract lists a number of constraints, the function can
be coded assuming these are honoured and can can enforce this though
assert.

If you are going to add an option to report rather than abort, you are
opening up a vast can of UB worms - what does the function do if any of
its constraints are violated?

Well, if you see the design of strncpy_s in my post you will see
that all constraints are grouped in an if statement.

The else part follows the specifications when the constraints are
NOT there, i.e. what now runs under "unspecified behavior" *IS*
specified, as you can see.

Other functions may have different specs, but in most cases a
meaningful behavior under error is possible. Note that this
happens only if the handler function does NOT abort or make
a long jump out of that context in a pre-established recovery
context...

Then how do you differentiate between a constraint than can and one that
can't be violated?

In C++ we'd use a mix of asserts and exceptions to do this, but C lacks
this feature, so how would you report a constraint violation to the
caller without some form of asynchronous callback?

In the cases where meaningful behaviour under error is possible, I'd
have thought this behaviour would involve some form of notification to
the caller.
A detected run time constraint violation provokes calling the handler
function. IF the handler returns (if it doesn't call abort) all "safer"
functions return a negative value.

In case there were NO constraint violations, all those functions return
zero.
Jul 7 '06 #5
jacob navia wrote:
Ian Collins a écrit :
>jacob navia wrote:
>>Ian Collins a écrit :
Isn't this all rather dangerous?

If a function's contract lists a number of constraints, the function
can
be coded assuming these are honoured and can can enforce this though
assert.

If you are going to add an option to report rather than abort, you are
opening up a vast can of UB worms - what does the function do if any of
its constraints are violated?
Well, if you see the design of strncpy_s in my post you will see
that all constraints are grouped in an if statement.

The else part follows the specifications when the constraints are
NOT there, i.e. what now runs under "unspecified behavior" *IS*
specified, as you can see.

Other functions may have different specs, but in most cases a
meaningful behavior under error is possible. Note that this
happens only if the handler function does NOT abort or make
a long jump out of that context in a pre-established recovery
context...

Then how do you differentiate between a constraint than can and one that
can't be violated?

In C++ we'd use a mix of asserts and exceptions to do this, but C lacks
this feature, so how would you report a constraint violation to the
caller without some form of asynchronous callback?

In the cases where meaningful behaviour under error is possible, I'd
have thought this behaviour would involve some form of notification to
the caller.

A detected run time constraint violation provokes calling the handler
function. IF the handler returns (if it doesn't call abort) all "safer"
functions return a negative value.

In case there were NO constraint violations, all those functions return
zero.
Yes, but how can the caller be notified? A handler in isolation isn't a
great deal of use.

That's the key with exceptions, a run time exception condition can be
passed back to the caller.

--
Ian Collins.
Jul 7 '06 #6
Ian Collins <ia******@hotmail.comwrote:
jacob navia wrote:

[long explanation snipped]

Since the handler function can be changed with the function
set_constraint_handler(), you can modify the handler to just log the
errors instead of aborting the program, mailing you an error report
if it detects an internet connection, or whatever.

True, you can say that the assert macro is already there, but it doesn't
have the possibility of dynamically changing the handler according to
the importance of the failure, like this one has.
Isn't this all rather dangerous?

If a function's contract lists a number of constraints, the function can
be coded assuming these are honoured and can can enforce this though assert.

If you are going to add an option to report rather than abort, you are
opening up a vast can of UB worms - what does the function do if any of
its constraints are violated?
Punt to the try/exception handler, of course.

What, you mean that doesn't exist in ISO C? Gosh.

[ Follow-ups set to where they should go. ]

Richard
Jul 7 '06 #7
Richard Bos wrote:
Ian Collins <ia******@hotmail.comwrote:

>>jacob navia wrote:

[long explanation snipped]
>>>Since the handler function can be changed with the function
set_constraint_handler(), you can modify the handler to just log the
errors instead of aborting the program, mailing you an error report
if it detects an internet connection, or whatever.

True, you can say that the assert macro is already there, but it doesn't
have the possibility of dynamically changing the handler according to
the importance of the failure, like this one has.

>>Isn't this all rather dangerous?

If a function's contract lists a number of constraints, the function can
be coded assuming these are honoured and can can enforce this though assert.

If you are going to add an option to report rather than abort, you are
opening up a vast can of UB worms - what does the function do if any of
its constraints are violated?


Punt to the try/exception handler, of course.

What, you mean that doesn't exist in ISO C? Gosh.

[ Follow-ups set to where they should go. ]

Richard
And that is all you have to say?

Impressing.

:-)

jacob
Jul 7 '06 #8

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

9
by: Mark Twombley | last post by:
Hi, I'm just getting back into C++ and had a question about the best practice for assigning error numbers. I have been working in VB for sometime now and there you would start assigning error...
6
by: vkreddy_in | last post by:
HI Currently i am handling excpetion using TRY/catch in my code.I am looking for solution some thing like this. if an excrption is occured then 1.call a CALLBACK function in a DLL 2.print the...
3
by: Agnes | last post by:
My client hold its MS SQL server in hkbranch, Both china and hong kong office can run the vb.net application very well via VPN. Now, they want to reduce cost and move the MS SQL server to china 's...
14
by: Mr Newbie | last post by:
I am often in the situation where I want to act on the result of a function, but a simple boolean is not enough. For example, I may have a function called isAuthorised ( User, Action ) as ?????...
21
by: Rajen | last post by:
When I run this program. #include<stdio.h> int main() { FILE *fp; int i; float f; char str;
11
by: Don | last post by:
When using Visual Basic .NET with a reference to Interop.Outlook, is there a way to get more detailed information about an error other than Exception.Message or Exception.ToString? For example,...
6
by: john_c | last post by:
FxCopy says this about catching general exceptions: "You should not catch Exception or SystemException. Catching generic exception types can hide run-time problems from the library user, and can...
0
NeoPa
by: NeoPa | last post by:
Table of Contents - Previous Chapter - ----------------------------------------------------------------------------------------------- 3) General Tips. The first and most important tip is...
18
by: pereges | last post by:
Hi, I'm thinking of having a seperate module in my project that deals with the exceptions and errors as they occur in a C program. Is this a good idea ? I thought of doing this because it is...
1
isladogs
by: isladogs | last post by:
The next online meeting of the Access Europe User Group will be on Wednesday 6 Dec 2023 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, Mike...
0
by: jianzs | last post by:
Introduction Cloud-native applications are conventionally identified as those designed and nurtured on cloud infrastructure. Such applications, rooted in cloud technologies, skillfully benefit from...
0
by: mar23 | last post by:
Here's the situation. I have a form called frmDiceInventory with subform called subfrmDice. The subform's control source is linked to a query called qryDiceInventory. I've been trying to pick up the...
0
by: abbasky | last post by:
### Vandf component communication method one: data sharing ​ Vandf components can achieve data exchange through data sharing, state sharing, events, and other methods. Vandf's data exchange method...
0
by: fareedcanada | last post by:
Hello I am trying to split number on their count. suppose i have 121314151617 (12cnt) then number should be split like 12,13,14,15,16,17 and if 11314151617 (11cnt) then should be split like...
0
by: stefan129 | last post by:
Hey forum members, I'm exploring options for SSL certificates for multiple domains. Has anyone had experience with multi-domain SSL certificates? Any recommendations on reliable providers or specific...
0
Git
by: egorbl4 | last post by:
Скачал я git, хотел начать настройку, а там вылезло вот это Что это? Что мне с этим делать? ...
1
by: davi5007 | last post by:
Hi, Basically, I am trying to automate a field named TraceabilityNo into a web page from an access form. I've got the serial held in the variable strSearchString. How can I get this into the...
0
by: MeoLessi9 | last post by:
I have VirtualBox installed on Windows 11 and now I would like to install Kali on a virtual machine. However, on the official website, I see two options: "Installer images" and "Virtual machines"....

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.