Error discovery and recovery in C 
Author Message
 Error discovery and recovery in C

Dear C programmers,
let's assume we have this well known function

strcpy(char * dest, const char *src)

It comes along with this description:

 The  strcpy() function copies the string pointed to by src
 (including the terminating `\0' character)  to  the  array
 pointed  to by dest.  The strings may not overlap, and the
 destination string dest must be large  enough  to  receive
 the copy.

Yes, I'm still aware that strncpy does exist too, but let's put it
aside for the moment.

Now we have some cases
strlen (dest) >= strlen(src)
fine no problem at all
strlen(dest) < strlen(src)
well bad programming *should* not happen.
But unfortunatly does over and over and over again.
what if dest == NULL or src == NULL?
Again,should not happen, but does ...

Now let's assume I write a "safe" alternative. I would argue that a
safe alternative should check at least that writing offer bound is not
possible. I could e.g reallocate ennough space that it fits.

Is it
a) a good idea to do that automatically?
b) if the answer to a) is no how to get feedback from the user.

I can imagine some alternatives
char*  my_strcpy(char * dest, const char *src)
/* Copy the contents of src into dest, if strlen(dest) is too
small to fit all elements of src, do a resize.
If resizing failes set errno to NO_MORE_MEMORY and return NULL, do not
touch dest.
If src == NULL set errno to INVALID_SOURCE and return NULL, do not
touch dest
If dest and src do overlop set errno to OVERLAPPING_REGIONS and return
NULL, do not touch dest
If src != NULL && dest == NULL set dest to source and return a pointer
to dest.
Otherwise copy src to dest and return a pointer to dest.
*/

Or something along that lines....

But how would I do if I wanted the user (if available) to tell me what
to do? And how to get that error handling away from the task of the
copy function?

if I clutter my_strpy with this
char* my_strcpy(char *dest, const char *src)
      if (NULL == src){
        if (interacitve){
          action = ask_user_for_action(....)
          action ();
        }  
      }
      if (NULL == dest)
         if (interactive)
           ....

      if (strlen(dest) < strlen(src))
         if (interactive
.....
      if (overlap(dest, src)
         if (interactive)
          ....

Well I would argue this is really ugly. And my copying get's burried
somewhere down all the ifs. And it's not extensible. If I feel somtime
that another stratey is appropriate I have to rewrite this code and
code which depends on this... This is hardly tolerable

Ok I could use setjmp/longjmp to get error handling away from the real
algorithm. But I better be prepared for it.

Could you point out other probably more elegant and easier to extend
alternatives? Or point me to some comparisons of the different error
detection and recovery strategies in C?

Thanks
Friedrich



Sat, 05 Feb 2005 00:41:57 GMT  
 Error discovery and recovery in C

Quote:

> Dear C programmers,
> let's assume we have this well known function

> strcpy(char * dest, const char *src)

> It comes along with this description:

>  The  strcpy() function copies the string pointed to by src
>  (including the terminating `\0' character)  to  the  array
>  pointed  to by dest.  The strings may not overlap, and the
>  destination string dest must be large  enough  to  receive
>  the copy.

> Yes, I'm still aware that strncpy does exist too, but let's put it
> aside for the moment.

> Now we have some cases
> strlen (dest) >= strlen(src)
> fine no problem at all
> strlen(dest) < strlen(src)
> well bad programming *should* not happen.
> But unfortunatly does over and over and over again.
> what if dest == NULL or src == NULL?
> Again,should not happen, but does ...

> Now let's assume I write a "safe" alternative. I would argue that a
> safe alternative should check at least that writing offer bound is not
> possible. I could e.g reallocate ennough space that it fits.

> Is it
> a) a good idea to do that automatically?
> b) if the answer to a) is no how to get feedback from the user.

> I can imagine some alternatives
> char*  my_strcpy(char * dest, const char *src)
> /* Copy the contents of src into dest, if strlen(dest) is too
> small to fit all elements of src, do a resize.
> If resizing failes set errno to NO_MORE_MEMORY and return NULL, do not
> touch dest.
> If src == NULL set errno to INVALID_SOURCE and return NULL, do not
> touch dest
> If dest and src do overlop set errno to OVERLAPPING_REGIONS and return
> NULL, do not touch dest
> If src != NULL && dest == NULL set dest to source and return a pointer
> to dest.
> Otherwise copy src to dest and return a pointer to dest.
> */

> Or something along that lines....

> But how would I do if I wanted the user (if available) to tell me what
> to do? And how to get that error handling away from the task of the
> copy function?

> if I clutter my_strpy with this
> char* my_strcpy(char *dest, const char *src)
>       if (NULL == src){
>         if (interacitve){
>           action = ask_user_for_action(....)
>           action ();
>         }  
>       }
>       if (NULL == dest)
>          if (interactive)
>            ....

>       if (strlen(dest) < strlen(src))
>          if (interactive
> .....
>       if (overlap(dest, src)
>          if (interactive)
>           ....

> Well I would argue this is really ugly. And my copying get's burried
> somewhere down all the ifs. And it's not extensible. If I feel somtime
> that another stratey is appropriate I have to rewrite this code and
> code which depends on this... This is hardly tolerable

> Ok I could use setjmp/longjmp to get error handling away from the real
> algorithm. But I better be prepared for it.

> Could you point out other probably more elegant and easier to extend
> alternatives? Or point me to some comparisons of the different error
> detection and recovery strategies in C?

> Thanks
> Friedrich

Hope you realize that dest in strcpy does not need to be a
null-terminated string at all, in which case there is no way to
determine the size of the array dest except by passing it in as an extra
parameter.  Once you do that, you might as well use strncpy instead of
re-inventing the wheel, unless that's the sort of thing you wish to do.

-nrk.



Sat, 05 Feb 2005 01:12:48 GMT  
 Error discovery and recovery in C

Quote:

>Dear C programmers,
>let's assume we have this well known function
>strcpy(char * dest, const char *src)
>It comes along with this description:
> The  strcpy() function copies the string pointed to by src
> (including the terminating `\0' character)  to  the  array
> pointed  to by dest.  The strings may not overlap, and the
> destination string dest must be large  enough  to  receive
> the copy.
>Yes, I'm still aware that strncpy does exist too, but let's put it
>aside for the moment.
>Now we have some cases
>strlen (dest) >= strlen(src)
>fine no problem at all
>strlen(dest) < strlen(src)
>well bad programming *should* not happen.

No, this is completely harmless. A problem arises if dest points to
the first on n consequitive allocated char elements and if n is
smaller than strlen(src) + 1.

Quote:
>But unfortunatly does over and over and over again.
>what if dest == NULL or src == NULL?

The behaviour is undefined.

Quote:
>Again,should not happen, but does ...
>Now let's assume I write a "safe" alternative. I would argue that a
>safe alternative should check at least that writing offer bound is not
>possible. I could e.g reallocate ennough space that it fits.

This is a bad idea, if you want to keep the interface of strcpy().

Quote:
>Is it
>a) a good idea to do that automatically?

If you keep the interface of strcpy(), there is no way you can
do it, anyway.  

Quote:
>b) if the answer to a) is no how to get feedback from the user.

General idea: Not applicable to strcpy(), because that is a
function form the standard C library, but applicable to
my_strcpy(). Pass an informative, if possible unique, error
code back to the caller. Proceed until you are close enough
to the user/not user to decide if you want to give
the user a choice.

Alternative: pass an user-interaction-context down to all
your low-level functions and give your user choices through
that user-interaction-context.

Quote:
>I can imagine some alternatives
>char*  my_strcpy(char * dest, const char *src)
>/* Copy the contents of src into dest, if strlen(dest) is too
>small to fit all elements of src, do a resize.

Forget about strlen(dest), and forget about resize. Consider:

  void foo()
  {
     char destination[128] = "";
     my_strcpy(destination, "mu");

     /* Process destination */
  }

strlen(dest) is 0, but dest points to enough memory for 42 copies of
src.

resizing a local array in the calling function is not possible in strcpy.
passing a pointer that was not recived from malloc or realloc as a first
parameter to realloc results in undefined behaviour.

Quote:
>If resizing failes set errno to NO_MORE_MEMORY and return NULL, do not
>touch dest.
>If src == NULL set errno to INVALID_SOURCE and return NULL, do not
>touch dest
>If dest and src do overlop set errno to OVERLAPPING_REGIONS and return
>NULL, do not touch dest

If src and dest to not point to the same object, it depends on your
implementation whether you have a chance to verify that the regions
do not overlap.

In portable C, you cannot check for the condition you want to
report. Differences between pointers are defined within objects
(including the first byte beyond the end of the object)

Quote:
>if I clutter my_strpy with this
>char* my_strcpy(char *dest, const char *src)
>      if (NULL == src){
>        if (interacitve){
>          action = ask_user_for_action(....)
>          action ();

ask_user_for_action returns a pointer to a function that takes
no arguments? Why not have it return an integral value that
you can switch on? For a choice of strategy, this is probably a
good solution in C.

Quote:
>        }  
>      }
>      if (NULL == dest)
>         if (interactive)
>           ....
>      if (strlen(dest) < strlen(src))
>         if (interactive
>.....
>      if (overlap(dest, src)
>         if (interactive)
>          ....
>Well I would argue this is really ugly. And my copying get's burried
>somewhere down all the ifs. And it's not extensible. If I feel somtime
>that another stratey is appropriate I have to rewrite this code and
>code which depends on this... This is hardly tolerable

How would you solve this problem in a language that is not as low
level as C?  

Kurt

--
| Kurt Watzka                            



Sat, 05 Feb 2005 01:51:03 GMT  
 Error discovery and recovery in C

Quote:

> Dear C programmers,
> strlen(dest) < strlen(src)
> well bad programming *should* not happen.
> But unfortunatly does over and over and over again.
> what if dest == NULL or src == NULL?
> Again,should not happen, but does ...

One of the features of C is that, if passed a pointer, there is no way of
knowing how much memory it points to.
This is a flaw in the language (it disappears with Java, or the C++ Standard
templete library) but is unavoidable if we wish to remain close to the
machine level.
You simply have to ensure that strcpy(dest, src) does not overflow the
destination buffer, possibly by using strlen() on src.

You could write an
 int flexstrcpy(char **dest, const char *src)
{
  temp = realloc(*dest, strlen(src) + 1);
  if(!temp)
    return -1; /* error */
  *dest = temp;
  strcpy(*dest, src);

  return 0;

Quote:
}

Which would have to be specified that dest is a pointer allocated with
malloc().


Sat, 05 Feb 2005 02:36:17 GMT  
 Error discovery and recovery in C

Quote:

> [... strcpy() is dangerous with a too-small destination ...]
> Now let's assume I write a "safe" alternative. I would argue that a
> safe alternative should check at least that writing offer bound is not
> possible. I could e.g reallocate ennough space that it fits.

> Is it
> a) a good idea to do that automatically?
> b) if the answer to a) is no how to get feedback from the user.
> [...]

    First things first: safe_strcpy(char*, const char*) has no
way to find out how large the destination area is.  strlen()
will not help, because the destination need not hold a valid
string.  Even if it does, the string might not fill the entire
destination area, so the string length could understate the
area size.

    So the task you have set for yourself is impossible (at
least, it's impossible unless you change the "signature" of
the function).  Still, I'd like to discuss your questions
(a) and (b), because similar questions arise in the design
of other interfaces.  So let's pretend for a moment that there
is some magical way to determine the size of the destination
area (there isn't, but let's pretend).

    Question (a) boils down to "If the function detects a
violation of its interface `contract', should it attempt to
repair the problem?"  There are exceptions to every design
rule, but I think the answer should usually be "No."  If
safe_strcpy() detects that the output area is too small, it
should not just attempt to reallocate it.  The output area
might not have been obtained from malloc(), so it might not
be realloc()-able.  Even if it is, calling realloc() might
move the area, making all the program's pointers to the old
area invalid.  And, of course, the destination area might
merely be part of a larger aggregate whose structure would
be unknown to safe_strcpy().

    Question (b) is "If a function detects a violation of
its interface `contract', how can it obtain guidance from
the user about what it should do?"  This, I think, is a poor
way of thinking, because it leads to programs which cannot
run unattended.  Why assume that a user or any other such
"higher authority" is baby-sitting the program?  Even if you
do assume your program has a human slave to give it advice,
why suppose that this slave knows enough about the internals
of the program to be able to give *good* advice?  Some program
grinds away for a while and suddenly says "Destination too
small: Abort, Fail, Retry?" -- how is the slave supposed to
know what answer makes sense?

    The unasked question is "If a function detects a violation
of its interface `contract', what should it do?"  There's no
one-size-fits-all, works-in-every-circumstance answer.  A
function like safe_strcpy() could, perhaps, do nothing and
return a NULL to indicate that the call didn't succeed.  Or
it could emit a diagnostic message and abort the program.  In
some languages it could generate an exception (something of
the sort is possible even in C, if the program maintains the
necessary reporting mechanisms).  All of these approaches (and
others not mentioned) have their merits -- but "Throw a blanket
over the problem" and "Appeal to higher authority" have few.

--



Sat, 05 Feb 2005 01:55:05 GMT  
 Error discovery and recovery in C

Quote:

> Dear C programmers,
> let's assume we have this well known function

> strcpy(char * dest, const char *src)

> It comes along with this description:

>  The  strcpy() function copies the string pointed to by src
>  (including the terminating `\0' character)  to  the  array
>  pointed  to by dest.  The strings may not overlap, and the
>  destination string dest must be large  enough  to  receive
>  the copy.

> Yes, I'm still aware that strncpy does exist too, but let's put it
> aside for the moment.

> Now we have some cases
> strlen (dest) >= strlen(src)
> fine no problem at all
> strlen(dest) < strlen(src)
> well bad programming *should* not happen.

Note that dest need not be a string. As long as there is sufficient
memory available in the location pointed to by dest, there is no need
for the memory to be initialised or to have a determinate value.

Quote:
> But unfortunatly does over and over and over again.
> what if dest == NULL or src == NULL?
> Again,should not happen, but does ...

Agreed. On the other hand, we don't want to penalise people who use the
function properly.

Quote:
> Now let's assume I write a "safe" alternative.

As long as it has a different name, that's fine.

Quote:
> I would argue that a
> safe alternative should check at least that writing offer bound is not
> possible. I could e.g reallocate ennough space that it fits.

> Is it
> a) a good idea to do that automatically?

Yes, I think so. My own dynamic string library will automatically
resize, at any rate.

Quote:
> b) if the answer to a) is no how to get feedback from the user.

Parameter? maxdestsize or similar.

Quote:

> I can imagine some alternatives
> char*  my_strcpy(char * dest, const char *src)
> /* Copy the contents of src into dest, if strlen(dest) is too
> small to fit all elements of src, do a resize.
> If resizing failes set errno to NO_MORE_MEMORY and return NULL, do not
> touch dest.
> If src == NULL set errno to INVALID_SOURCE and return NULL, do not
> touch dest
> If dest and src do overlop set errno to OVERLAPPING_REGIONS and return
> NULL, do not touch dest
> If src != NULL && dest == NULL set dest to source and return a pointer
> to dest.
> Otherwise copy src to dest and return a pointer to dest.
> */

This sounds terribly complicated. Also, note that you are assuming dest
was allocated via malloc or realloc, and is thus resizeable. That might
not be the case. Also, if you're going to resize, don't you think you
should take char **?

Quote:

> Or something along that lines....

> But how would I do if I wanted the user (if available) to tell me what
> to do?

Parameterisation is one way. Multiple functions, each doing slightly
different things, is another.

Quote:
> And how to get that error handling away from the task of the
> copy function?

Return 0 for success, non-zero for "um, hey guys, what now?"

- Show quoted text -

Quote:

> if I clutter my_strpy with this
> char* my_strcpy(char *dest, const char *src)
>       if (NULL == src){
>         if (interacitve){
>           action = ask_user_for_action(....)
>           action ();
>         }
>       }
>       if (NULL == dest)
>          if (interactive)
>            ....

>       if (strlen(dest) < strlen(src))
>          if (interactive
> .....
>       if (overlap(dest, src)
>          if (interactive)
>           ....

> Well I would argue this is really ugly.

Quite so. K&R's strcpy is elegant, but then it trusts the programmer.
Once you start putting up fences, the photogenic nature of the landscape
is reduced. This is sometimes unavoidable.

<snip>

Quote:
> Could you point out other probably more elegant and easier to extend
> alternatives? Or point me to some comparisons of the different error
> detection and recovery strategies in C?

I use a very simple (some would say, simple-minded) approach to
error-handling. I have two kinds of functions: functions which return
pointers, and functions which don't. My functions that return pointers
will always return NULL if something went wrong. My functions that don't
return pointers will always return non-zero if something went wrong.
This makes it nice and easy to handle errors at the calling level.

As for robustifying strcpy, why not write a dynamic string library,
using a new composite type to describe the string? For example:

typedef struct DominicusDynamicString_
{
  char *s;
  size_t currsize;
  size_t maxsize;

Quote:
} DominicusDynamicString;

It's fairly easy to write a set of str*like functions to handle dynamic
strings.

--

"Usenet is a strange place." - Dennis M Ritchie, 29 July 1999.
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
K&R answers, C books, etc: http://users.powernet.co.uk/eton



Sat, 05 Feb 2005 03:21:12 GMT  
 Error discovery and recovery in C

Quote:


> > Dear C programmers,
> > strlen(dest) < strlen(src)
> > well bad programming *should* not happen.
> > But unfortunatly does over and over and over again.
> > what if dest == NULL or src == NULL?
> > Again,should not happen, but does ...

> One of the features of C is that, if passed a pointer, there is no way of
> knowing how much memory it points to.

That's wrong. If (a function is) passed a pointer, it can also be passed
a size parameter, should one be necessary. This is a perfectly sensible
way to know to how much memory the pointer points.

Quote:
> This is a flaw in the language

No, it's not. It's a feature. When the size is not required, what
possible benefit can there be in making it available? When the size *is*
required, it can be remembered - by the programmer.

<snip>

--

"Usenet is a strange place." - Dennis M Ritchie, 29 July 1999.
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
K&R answers, C books, etc: http://users.powernet.co.uk/eton



Sat, 05 Feb 2005 03:38:55 GMT  
 Error discovery and recovery in C


Quote:

>> [... strcpy() is dangerous with a too-small destination ...]
>> Now let's assume I write a "safe" alternative. I would argue that a
>> safe alternative should check at least that writing offer bound is not
>> possible. I could e.g reallocate ennough space that it fits.

>> Is it
>> a) a good idea to do that automatically?
>> b) if the answer to a) is no how to get feedback from the user.
>> [...]

>of the program to be able to give *good* advice?  Some program
>grinds away for a while and suddenly says "Destination too
>small: Abort, Fail, Retry?" -- how is the slave supposed to
>know what answer makes sense?

Since they won't know which answer is best, clearly the right thing to
do is not accept any answer: no matter what they type, just keep
repeating the question, until they reboot.  This will give the user
the greatest feeling of familiarity, and is thus in keeping with the
principle of "Least Astonishment".

--Ben

(PS: :))

--



Sat, 05 Feb 2005 04:56:42 GMT  
 Error discovery and recovery in C

Quote:

> Hope you realize that dest in strcpy does not need to be a
> null-terminated string at all, in which case there is no way to
> determine the size of the array dest except by passing it in as an
> extra parameter.  Once you do that, you might as well use strncpy
> instead of re-inventing the wheel, unless that's the sort of thing you
> wish to do.

Well let's see what the manual pages say about strncpy
The  strncpy()  function  is similar, except that not more
than n bytes of src are copied. Thus, if there is no  null
byte  among  the first n bytes of src, the result will not
be null-terminated.

So what does strnpy buy me than?

And the overlapping stuff still exists too. And even if I provide the
count than I have to be sure that dest offers enough space.  I suggest
you read what strncpy is supposed to do an you'll see that it lacks
things too.

Friedrich



Sat, 05 Feb 2005 12:57:56 GMT  
 Error discovery and recovery in C

Quote:


> >Dear C programmers,
> >let's assume we have this well known function

> >strcpy(char * dest, const char *src)

> >It comes along with this description:

> > The  strcpy() function copies the string pointed to by src
> > (including the terminating `\0' character)  to  the  array
> > pointed  to by dest.  The strings may not overlap, and the
> > destination string dest must be large  enough  to  receive
> > the copy.

> >Yes, I'm still aware that strncpy does exist too, but let's put it
> >aside for the moment.

> >Now we have some cases
> >strlen (dest) >= strlen(src)
> >fine no problem at all
> >strlen(dest) < strlen(src)
> >well bad programming *should* not happen.

> No, this is completely harmless. A problem arises if dest points to
> the first on n consequitive allocated char elements and if n is
> smaller than strlen(src) + 1.

Well I missed it, sorry.

Quote:

> >But unfortunatly does over and over and over again.
> >what if dest == NULL or src == NULL?

> The behaviour is undefined.

Well I do not want to have undefined behavious therefor I ask fo the alternatives.
Quote:

> >Again,should not happen, but does ...

> >Now let's assume I write a "safe" alternative. I would argue that a
> >safe alternative should check at least that writing offer bound is not
> >possible. I could e.g reallocate ennough space that it fits.

> This is a bad idea, if you want to keep the interface of strcpy().
You're right.

> >Is it
> >a) a good idea to do that automatically?

> If you keep the interface of strcpy(), there is no way you can
> do it, anyway.  

Agreed.

Quote:

> If src and dest to not point to the same object, it depends on your
> implementation whether you have a chance to verify that the regions
> do not overlap.

> In portable C, you cannot check for the condition you want to
> report. Differences between pointers are defined within objects
> (including the first byte beyond the end of the object)

Thanks for that clarification.
Quote:

> >if I clutter my_strpy with this
> >char* my_strcpy(char *dest, const char *src)
> >      if (NULL == src){
> >        if (interacitve){
> >          action = ask_user_for_action(....)
> >          action ();

> ask_user_for_action returns a pointer to a function that takes
> no arguments? Why not have it return an integral value that
> you can switch on? For a choice of strategy, this is probably a
> good solution in C.

Well as I pointed out it was an example, but I see the point.

Quote:

> How would you solve this problem in a language that is not as low
> level as C?  

I do not understand this question. I want a nice solution in C and do
not care about another language.

Regards
Friedrich



Sat, 05 Feb 2005 13:11:52 GMT  
 Error discovery and recovery in C

Quote:

> > Could you point out other probably more elegant and easier to extend
> > alternatives? Or point me to some comparisons of the different error
> > detection and recovery strategies in C?

> I use a very simple (some would say, simple-minded) approach to
> error-handling. I have two kinds of functions: functions which return
> pointers, and functions which don't. My functions that return pointers
> will always return NULL if something went wrong. My functions that don't
> return pointers will always return non-zero if something went wrong.
> This makes it nice and easy to handle errors at the calling level.

> As for robustifying strcpy, why not write a dynamic string library,
> using a new composite type to describe the string? For example:

> typedef struct DominicusDynamicString_
> {
>   char *s;
>   size_t currsize;
>   size_t maxsize;
> } DominicusDynamicString;

Well this is what I've done. And in fact all String handling is based
on dynamic allocation. My idea was anyway to have something like
Pseudo Code

void my_strcpy(STRING dest, const STRING src)
  check_arguments
  if (some things failed)
     ReportError
     Error handling
     ....

  And that's why I wonder what a good approach would be. I wonder how
a user can hook, by register an Error handler for that function.

E.g If dest would be an invalid STRING but src is valid, allocate
enough space to fit source and copy it onto it.

Quote:

> It's fairly easy to write a set of str*like functions to handle dynamic
> strings.

Well I agree it is not difficult, but what I find difficult is find a
nice and clean interface for Error handling..

Regards
Friedrich



Sat, 05 Feb 2005 13:26:31 GMT  
 Error discovery and recovery in C

Quote:

>     Question (a) boils down to "If the function detects a
> violation of its interface `contract', should it attempt to
> repair the problem?"  There are exceptions to every design
> rule, but I think the answer should usually be "No."

Well my interface contract could be like this

void my_strcpy(STRING dest, const STRING src){
        /* Copy src to dest.

        check_1 src valid?
          if not call user-provided function for handling it, default
         to some action....
        check_2 dest valid?
        check_3 enough space in dest
           if not call user-provided function ....
etc etc.

 ....
The contract is quite simple Either I do get my copy or nothing at
all or...

Quote:
>  If
> safe_strcpy() detects that the output area is too small, it
> should not just attempt to reallocate it.  The output area
> might not have been obtained from malloc(), so it might not
> be realloc()-able.

I disagree. I wanted all my strings to be dynamically allocatead and
shrink or grow as needed. I do not think it's good idea escpecially
for "strings" to be of fixed length.

Quote:
>     Question (b) is "If a function detects a violation of
> its interface `contract', how can it obtain guidance from
> the user about what it should do?"  This, I think, is a poor
> way of thinking, because it leads to programs which cannot
> run unattended.  

Well I disagree again. I may be willing to let the user decide how to
proceed probably programatically. E.g I could say
if the target of the copy is invalid, run an Error handler.
This Error handler can be overwritten by the user. E.g someone like to
crash as early as possible whereas another thinks that it ok to make
target proper.

Regards
Friedrich



Sat, 05 Feb 2005 13:41:40 GMT  
 Error discovery and recovery in C

Quote:

>> >if I clutter my_strpy with this
>> >char* my_strcpy(char *dest, const char *src)
>> >      if (NULL == src){
>> >        if (interacitve){
>> >          action = ask_user_for_action(....)
>> >          action ();

>> ask_user_for_action returns a pointer to a function that takes
>> no arguments? Why not have it return an integral value that
>> you can switch on? For a choice of strategy, this is probably a
>> good solution in C.
>Well as I pointed out it was an example, but I see the point.

>> How would you solve this problem in a language that is not as low
>> level as C?  
>I do not understand this question. I want a nice solution in C and do
>not care about another language.

In most langagues, including C, the only way to jump from some subroutine
to an interactive error handling code and back to the source of the
error condition is a funktion call from the low level routine. Since
the error handling/decision making facility might need context information,
passing around an error reporting context may be a good idea.

  Please consider this: The caller might know that he is trying to
copy 8193 characters to the persons given name and produce an meaning-
full error message. The low level routine cannot tell why someone
is trying to copy 8193 characters to a 64 byte destination buffer.
So, passing an error code back to the caller until you have enough
information what to do looks like a better strategy to me.

  If you are trying to copy the 8193 byte thesis to a 4096 character
buffer that could hold the pevious version, reallocation to 16384
might be a good idea.

  You know languages that support exceptions. One reason why exceptions
look like a good idea in error recovery is that you can automatically
pass up the error until you have reached a level of abstraction that
allows you to decide what to do. The C equivalent to an exception is
returning an error code from a low level function.

  Without a lot of context information even a user who knows the
program quite well cannot always decide what to do if the target
buffer is not big enough in strcpy().

  Jumping back down to the source of the error and continuing after
consulting the user about how the routine should proceed is rarely a
good idea. If you have expensive intermediate results that you want
to preserve, checkpoints in your algorthim might be a good idea.

  A programm to compute the F-blanket for a 5-dimensional R probability
field should write its current state to some kind of permanent storage
after every iteration and should be able to recover its state from
its log file. This way, the expected run time of the programm can be
reduced to half of the remainig time every 4 or 5 years, because the
programm can be ported to new and faster hardware. If you run into
a problem in a low level routine within one iteration, I agree that
it is a bad idea to return to the top-level routine and forget about
the intermediate results.

Kurt

--
| Kurt Watzka                            



Sun, 06 Feb 2005 02:22:26 GMT  
 Error discovery and recovery in C

Quote:


>>Hope you realize that dest in strcpy does not need to be a
>>null-terminated string at all, in which case there is no way to
>>determine the size of the array dest except by passing it in as an
>>extra parameter.  Once you do that, you might as well use strncpy
>>instead of re-inventing the wheel, unless that's the sort of thing you
>>wish to do.

> Well let's see what the manual pages say about strncpy
> The  strncpy()  function  is similar, except that not more
> than n bytes of src are copied. Thus, if there is no  null
> byte  among  the first n bytes of src, the result will not
> be null-terminated.

> So what does strnpy buy me than?

> And the overlapping stuff still exists too. And even if I provide the
> count than I have to be sure that dest offers enough space.  I suggest
> you read what strncpy is supposed to do an you'll see that it lacks
> things too.

> Friedrich

If you wish to kid yourself into thinking that you are the first ever
person to think of building safer C string manipulation functions, I am
not going to stop you.  Additionally, if you are ambitious enough to
think you can build a library that satisfies *every* possible user and
handles *all* possible use-cases and scenarios, all I can do is to wish
you good luck.

-nrk.



Sun, 06 Feb 2005 04:31:40 GMT  
 Error discovery and recovery in C

Quote:


>> Dear C programmers,
>> let's assume we have this well known function

>> strcpy(char * dest, const char *src)

>> It comes along with this description:

>>  The  strcpy() function copies the string pointed to by src
>>  (including the terminating `\0' character)  to  the  array
>>  pointed  to by dest.  The strings may not overlap, and the
>>  destination string dest must be large  enough  to  receive
>>  the copy.

>> Yes, I'm still aware that strncpy does exist too, but let's put it
>> aside for the moment.

[...]

Quote:

>Hope you realize that dest in strcpy does not need to be a
>null-terminated string at all, in which case there is no way to
>determine the size of the array dest except by passing it in as an extra
>parameter.  Once you do that, you might as well use strncpy instead of
>re-inventing the wheel, unless that's the sort of thing you wish to do.

strncpy() is a great example of a "square wheel" in C, which can benefit
by a good re-invention.  The problem is that it does not stop copying
characters when it hits the '\0' in the source array; instead, it keeps
writing chars to the target array until it has written the full <n>
requested -- the "excess" chars are all '\0'.  This can be a big
performance hit if typical strings are short, but buffers are large: a
very common situation.  OTOH, if strncpy() hits <n> *before* seeing the
'\0' in the source array, then it leaves the target array not
nul-terminated, i.e., not a valid string.  So generally, you either get
more nuls than you wanted, or fewer.

This behaviour has no usefulness that I know of.  Any obscure situation
where this is close to what is wanted, could probably be better served
by memcpy() or memmove().

Instead, it would of course be better if strncpy() (a) guaranteed that
the target string will always be nul-terminated (if n > 0 anyway), and
(b) stopped upon encountering the nul in the source string.  Since it
doesn't do these things, one ends up writing something that does.

--Ben

--



Sun, 06 Feb 2005 04:53:24 GMT  
 
 [ 20 post ]  Go to page: [1] [2]

 Relevant Pages 

1. Error handling / Error recovery.

2. error recovery philosophy

3. error analysis/handling/detecting/reporting/preventing/recovery/reproduce/debug

4. error recovery

5. yacc error recovery

6. Newbie: separate big .cs file into small .cs files

7. Compiler error CS 1595 - Help

8. tree recovery

9. CPU Type discovery

10. dynamic webservice discovery/access

11. Discovery Profile an there favorites

12. MTU path discovery

 

 
Powered by phpBB® Forum Software