Error returns and repeated code, GOTOs, etc.

  • Follow


Hi.

I've got some stuff that looks like this:

---
ErrorCode MyFunc()
{
          BigNum a, b, c, d;
          ErrorCode rv;

          rv = BigNum_Initialize(&a);
          if(rv != ERROR_SUCCESS)
            return(rv);

          rv = BigNum_Initialize(&b);
          if(rv != ERROR_SUCCESS)
          {
            BigNum_Free(&a); /* and what if THIS fails??? :) */
            return(rv);
          }

          rv = BigNum_Initialize(&c);
          if(rv != ERROR_SUCCESS)
          {
            BigNum_Free(&b);
            BigNum_Free(&a);
            return(rv);
          }

          rv = BigNum_Initialize(&d);
          if(rv != ERROR_SUCCESS)
          {
            BigNum_Free(&c);
            BigNum_Free(&b);
            BigNum_Free(&a);
            return(rv);
          }

          /* do some math */
          rv = BigNum_Set(&b, 3);
          if(rv != ERROR_SUCCESS)
          {
            BigNum_Free(&d);
            BigNum_Free(&c);
            BigNum_Free(&b);
            BigNum_Free(&a);
            return(rv);
          }

          ...

          /* free buffers */
          rv = BigNum_Free(&d);
          if(rv != ERROR_SUCCESS)
          {
            BigNum_Free(&c);
            BigNum_Free(&b);
            BigNum_Free(&a);
            return(rv);
          }

          rv = BigNum_Free(&c);
          if(rv != ERROR_SUCCESS)
          {
            BigNum_Free(&b);
            BigNum_Free(&a);
            return(rv);
          }

          rv = BigNum_Free(&b);
          if(rv != ERROR_SUCCESS)
          {
            BigNum_Free(&a);
            return(rv);
          }

          rv = BigNum_Free(&a);
          if(rv != ERROR_SUCCESS)
            return(rv);

          return(ERROR_SUCCESS);
}
---

But this is nasty, with all those duplicated "free" blocks. What can
be done to relieve this code duplication? It's ugly, it hurts my
freaking eyes and my nose is screaming for relief. And it hurts
maintainability to no end -- what if we decide to add more capability
to MyFunc() that requires additional bignums? Oy... We'd have to
update _all those blocks_.

I was thinking about using a "goto", but Gotos are Bad, aren't they? I
can't believe I may have to use a goto! What about Djikstra's famous
letter? Is it possible that perhaps a goto may be GOOD here? Because
with a goto this would all seem much simpler. If we violate Djikstra,
we get:

---

ErrorCode MyFunc()
{
          BigNum a, b, c, d;
          ErrorCode rv;

          rv = BigNum_Initialize(&a); if(rv != ERROR_SUCCESS) goto
fail0;
          rv = BigNum_Initialize(&b); if(rv != ERROR_SUCCESS) goto
fail1;
          rv = BigNum_Initialize(&c); if(rv != ERROR_SUCCESS) goto
fail2;
          rv = BigNum_Initialize(&d); if(rv != ERROR_SUCCESS) goto
fail3;

          /* do some math */
          rv = BigNum_Set(&b, 3); if(rv != ERROR_SUCCESS) goto fail4;

          ...

          /* free buffers */
          rv = BigNum_Free(&d); if(rv != ERROR_SUCCESS) goto fail3;
          rv = BigNum_Free(&c); if(rv != ERROR_SUCCESS) goto fail2;
          rv = BigNum_Free(&b); if(rv != ERROR_SUCCESS) goto fail1;
          rv = BigNum_Free(&a); if(rv != ERROR_SUCCESS) goto fail0;

          return(ERROR_SUCCESS);

fail4:    BigNum_Free(&d);
fail3:    BigNum_Free(&c);
fail2:    BigNum_Free(&b);
fail1:    BigNum_Free(&a);
fail0:    return(rv);
}
---

But we've violated Djikstra and we've used a "bad" goto. How would
_you_ write MyFunc() above?
0
Reply mike4ty4 (405) 5/30/2012 5:44:06 AM

On 2012-05-30, mike3 <mike4ty4@yahoo.com> wrote:
> Hi.
>
> I've got some stuff that looks like this:
>
> [stuff snipped]
>
> But this is nasty, with all those duplicated "free" blocks. What can
> be done to relieve this code duplication? It's ugly, it hurts my
> freaking eyes and my nose is screaming for relief. And it hurts
> maintainability to no end -- what if we decide to add more capability
> to MyFunc() that requires additional bignums? Oy... We'd have to
> update _all those blocks_.

ErrorCode MyFunc(void)
{
  BigNum a;
  ErrorCode rv = BigNum_Initialize(&a);
  if (rv == ERROR_SUCCESS)
  {
    BigNum b;
    rv = BigNum_Initialize(&b);
    if (rv == ERROR_SUCCESS)
    {
      BigNum c;
      rv = BigNum_Initialize(&c);
      if (rv == ERROR_SUCCESS)
      {
        BigNum d;
        rv = BigNum_Initialize(&d);
        if (rv == ERROR_SUCCESS)
        {
          /* do some math */
          rv = BigNum_Set(&b, 3);
          if (rv == ERROR_SUCCESS)
          {
            /* ... */
          }
          BigNum_Free(&d);
        }
        BigNum_Free(&c);
      }
      BigNum_Free(&b);
    }
    BigNum_Free(&a);
  }
  return rv;
}
0
Reply ike8 (164) 5/30/2012 6:38:41 AM


mike3 <mike4ty4@yahoo.com> wrote:
> But this is nasty, with all those duplicated "free" blocks. What can
> be done to relieve this code duplication? [...]

Add a garbage collector for BigNums.

-- 
Nils M Holm  < n m h @ t 3 x . o r g >  www.t3x.org
0
Reply news20091 (144) 5/30/2012 6:57:25 AM

=D7=91=D7=AA=D7=90=D7=A8=D7=99=D7=9A =D7=99=D7=95=D7=9D =D7=A8=D7=91=D7=99=
=D7=A2=D7=99, 30 =D7=91=D7=9E=D7=90=D7=99 2012 06:44:06 UTC+1, =D7=9E=D7=90=
=D7=AA mike3:
>=20
> But we've violated Djikstra and we've used a "bad" goto. How would
> _you_ write MyFunc() above?
>
I use gotos for handling memory allocation failures, but almost never for a=
ny other purpose.
--=20
Basic Algorithms - ANSI C source for fundamental programming operations.
http://www.malcolmmclean.site11.com/www
 =20
0
Reply malcolm.mclean5 (750) 5/30/2012 7:52:23 AM

On May 30, 1:52=C2=A0am, Malcolm McLean <malcolm.mcle...@btinternet.com>
wrote:
> =D7=91=D7=AA=D7=90=D7=A8=D7=99=D7=9A =D7=99=D7=95=D7=9D =D7=A8=D7=91=D7=
=99=D7=A2=D7=99, 30 =D7=91=D7=9E=D7=90=D7=99 2012 06:44:06 UTC+1, =D7=9E=D7=
=90=D7=AA mike3:
>
> > But we've violated Djikstra and we've used a "bad" goto. How would
> > _you_ write MyFunc() above?
>
> I use gotos for handling memory allocation failures, but almost never for=
 any other purpose.

So what would you do in the above circumstance?
0
Reply mike4ty4 (405) 5/30/2012 8:50:55 AM

On 05/30/2012 06:44 AM, mike3 wrote:

> But we've violated Djikstra and we've used a "bad" goto. How would
> _you_ write MyFunc() above?

I personally don't like the infinitely indented if approach...

In C, I think it's probably OK to use goto for "exception handling".

If you have some way of indicating that a BigNum is uninitialised (e.g. 
a BIGNUM_NULL macro) and you make BigNum_Free() set the BigNum to this 
value, you could use something like this - goto-rich but less repetitive:-

ErrorCode MyFunc()
{
           BigNum a = BIGNUM_NULL;
           BigNum b = BIGNUM_NULL;
           BigNum c = BIGNUM_NULL;
           BigNum d = BIGNUM_NULL;
           ErrorCode rv;

           rv = BigNum_Initialize(&a);
           if(rv != ERROR_SUCCESS)
            goto failed;

           rv = BigNum_Initialize(&b);
           if(rv != ERROR_SUCCESS)
            goto failed;

           rv = BigNum_Initialize(&c);
           if(rv != ERROR_SUCCESS)
            goto failed;

           rv = BigNum_Initialize(&d);
           if(rv != ERROR_SUCCESS)
            goto failed;

           /* do some math */
           rv = BigNum_Set(&b, 3);
           if(rv != ERROR_SUCCESS)
            goto failed;

           ...
          /* free buffers */
           rv = BigNum_Free(&d);
           if(rv != ERROR_SUCCESS)
            goto failed;

           rv = BigNum_Free(&c);
           if(rv != ERROR_SUCCESS)
            goto failed;

           rv = BigNum_Free(&b);
           if(rv != ERROR_SUCCESS)
            goto failed;

           rv = BigNum_Free(&a);
           if(rv != ERROR_SUCCESS)
            goto failed;

           return(ERROR_SUCCESS);

failed: /* we'll try and clean up, but won't care too much if it fails */
         if (d != BIGNUM_NULL)
           BigNum_Free(&d);
         if (c != BIGNUM_NULL)
           BigNum_Free(&c);
         if (b != BIGNUM_NULL)
           BigNum_Free(&b);
         if (a != BIGNUM_NULL)
           BigNum_Free(&a);

         return(rv);
}
0
Reply mark_bluemel (848) 5/30/2012 8:55:55 AM

MarkBluemel wrote:
) On 05/30/2012 06:44 AM, mike3 wrote:
)
)> But we've violated Djikstra and we've used a "bad" goto. How would
)> _you_ write MyFunc() above?
)
) I personally don't like the infinitely indented if approach...
)
) In C, I think it's probably OK to use goto for "exception handling".
)
) If you have some way of indicating that a BigNum is uninitialised (e.g. 
) a BIGNUM_NULL macro) and you make BigNum_Free() set the BigNum to this 
) value, you could use something like this - goto-rich but less repetitive:-

Rewritten to get rid of the gotos:

ErrorCode DoMath(BigNum a, BigNum b. BigNum c, BigNum d)
{
        ErrorCode rv;
        /* do some math */
        rv = BigNum_Set(&b, 3);
        if (rv != ERROR_SUCCESS) return rv;

        ...

        return ERROR_SUCCESS;
}
ErrorCode MyFunc()
{
        BigNum a = BIGNUM_NULL;
        BigNum b = BIGNUM_NULL;
        BigNum c = BIGNUM_NULL;
        BigNum d = BIGNUM_NULL;
        ErrorCode rv = ERROR_SUCCESS;

        if (rv == ERROR_SUCCESS) rv = BigNum_Initialize(&a);
        if (rv == ERROR_SUCCESS) rv = BigNum_Initialize(&b);
        if (rv == ERROR_SUCCESS) rv = BigNum_Initialize(&c);
        if (rv == ERROR_SUCCESS) rv = BigNum_Initialize(&d);

        if (rv == ERROR_SUCCESS) rv = DoMath(a, b, c, d);

        /* BigNum_Free should check for BIGNUM_NULL itself */
        BigNum_Free(&d);
        BigNum_Free(&c); 
        BigNum_Free(&b);
        BigNum_Free(&a);

        return rv;
}

If you want to be more concise, you can make ERROR_SUCCESS equal 0,
and then you can simply do:

    rv = BigNum_Initialize(&a) || ... || BigNum_Set(&b, 3) || BigNum_AddTo(&a, &b) || ... ;

Which will short-circuit at the first failure.

SaSW, Willem
-- 
Disclaimer: I am in no way responsible for any of the statements
            made in the above text. For all I know I might be
            drugged or something..
            No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
0
Reply willem6 (255) 5/30/2012 9:18:54 AM

On 05/30/12 05:44 PM, mike3 wrote:
> Hi.
>
> I've got some stuff that looks like this:
>
> ---
> ErrorCode MyFunc()
> {
>            BigNum a, b, c, d;
>            ErrorCode rv;
>
>            rv = BigNum_Initialize(&a);
>            if(rv != ERROR_SUCCESS)
>              return(rv);
>
>            rv = BigNum_Initialize(&b);
>            if(rv != ERROR_SUCCESS)
>            {
>              BigNum_Free(&a); /* and what if THIS fails??? :) */
>              return(rv);
>            }

<snip lots more of the same>

I know I'm inviting flames, but this really is a classic case where C++ 
if you have access to it can be used as a better C....

-- 
Ian Collins
0
Reply ian-news (9908) 5/30/2012 9:50:10 AM

=D7=91=D7=AA=D7=90=D7=A8=D7=99=D7=9A =D7=99=D7=95=D7=9D =D7=A8=D7=91=D7=99=
=D7=A2=D7=99, 30 =D7=91=D7=9E=D7=90=D7=99 2012 10:50:10 UTC+1, =D7=9E=D7=90=
=D7=AA Ian Collins:
> On 05/30/12 05:44 PM, mike3 wrote:
> > Hi.
> >
> > I've got some stuff that looks like this:
> >
> > ---
> > ErrorCode MyFunc()
> > {
> >            BigNum a, b, c, d;
> >            ErrorCode rv;
> >
> >            rv =3D BigNum_Initialize(&a);
> >            if(rv !=3D ERROR_SUCCESS)
> >              return(rv);
> >
> >            rv =3D BigNum_Initialize(&b);
> >            if(rv !=3D ERROR_SUCCESS)
> >            {
> >              BigNum_Free(&a); /* and what if THIS fails??? :) */
> >              return(rv);
> >            }
>
> I know I'm inviting flames, but this really is a classic case where C++=
=20
> if you have access to it can be used as a better C....
>=20
You want

rv =3D BigNum_Initilaize(&a);
if(rv)
  goto error_exit;
rv =3D BigNum_Add(&a, &b, &c);
if(!rv)
   goto error_exit;

it's slightly messier than exceptions, but unlike exceptions it's easier to=
 test and harder to abuse.
You don't want to be defining the symbol,ERROR_SUCCESS in a bignum.h header=
, and you don't want bignum.c dependent on myerrorcodes.h. However -1 for o=
ut of memory is pretty standard.


0
Reply malcolm.mclean5 (750) 5/30/2012 10:34:13 AM

On 05/30/12 10:34 PM, Malcolm McLean wrote:
> בתאריך יום רביעי, 30 במאי 2012 10:50:10 UTC+1, מאת Ian Collins:
>> On 05/30/12 05:44 PM, mike3 wrote:
>>> Hi.
>>>
>>> I've got some stuff that looks like this:
>>>
>>> ---
>>> ErrorCode MyFunc()
>>> {
>>>             BigNum a, b, c, d;
>>>             ErrorCode rv;
>>>
>>>             rv = BigNum_Initialize(&a);
>>>             if(rv != ERROR_SUCCESS)
>>>               return(rv);
>>>
>>>             rv = BigNum_Initialize(&b);
>>>             if(rv != ERROR_SUCCESS)
>>>             {
>>>               BigNum_Free(&a); /* and what if THIS fails??? :) */
>>>               return(rv);
>>>             }
>>
>> I know I'm inviting flames, but this really is a classic case where C++
>> if you have access to it can be used as a better C....
>>
> You want
>
> rv = BigNum_Initilaize(&a);
> if(rv)
>    goto error_exit;
> rv = BigNum_Add(&a,&b,&c);
> if(!rv)
>     goto error_exit;
>
> it's slightly messier than exceptions, but unlike exceptions it's easier to test and harder to abuse.

It's way uglier and no easier to test.

> You don't want to be defining the symbol,ERROR_SUCCESS in a bignum.h header, and you don't want bignum.c dependent on myerrorcodes.h. However -1 for out of memory is pretty standard.

I'm not sure what you are saying there.

-- 
Ian Collins
0
Reply ian-news (9908) 5/30/2012 10:57:04 AM

Malcolm McLean wrote:
) You want
)
) rv = BigNum_Initilaize(&a);
) if(rv)
)   goto error_exit;
) rv = BigNum_Add(&a, &b, &c);
) if(!rv)
)    goto error_exit;

Why one positive and one negative test?  Is that a typo?


SaSW, Willem
-- 
Disclaimer: I am in no way responsible for any of the statements
            made in the above text. For all I know I might be
            drugged or something..
            No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
0
Reply willem6 (255) 5/30/2012 11:04:48 AM

mike3 <mike4ty4@yahoo.com> writes:
>be done to relieve this code duplication? It's ugly, it hurts my

  The code below still has some duplication. I might write another
  post later with less duplication. But the code below should be
  structured and readable, but was not tested.

static ErrorCode MyFuncX
( BigNum const * const a,
  BigNum const * const b,
  BigNum const * const c,
  BigNum const * const d )
{ return BigNum_Set( &b, 3 ); }

static ErrorCode MyFuncD
( BigNum const * const a,
  BigNum const * const b,
  BigNum const * const c )
{ BigNum d;
  ErrorCode rv = BigNum_Initialize( &d );
  if( rv == ERROR_SUCCESS )
  { rv = MyFuncX( a, b, c, &d ); BigNum_Free( &d ); }
  return rv; }

static ErrorCode MyFuncC
( BigNum const * const a,
  BigNum const * const b )
{ BigNum c;
  ErrorCode rv = BigNum_Initialize( &c );
  if( rv == ERROR_SUCCESS )
  { rv = MyFuncD( a, b, &c ); BigNum_Free( &c ); }
  return rv; }

static ErrorCode MyFuncB( BigNum const * const a )
{ BigNum b;
  ErrorCode rv = BigNum_Initialize( &b );
  if( rv == ERROR_SUCCESS )
  { rv = MyFuncC( a, &b ); BigNum_Free( &b ); }
  return rv; }

ErrorCode MyFuncA( void )
{ BigNum a;
  ErrorCode rv = BigNum_Initialize( &a );
  if( rv == ERROR_SUCCESS )
  { rv = MyFuncB( &a ); BigNum_Free( &a ); }
  return rv; }

ErrorCode MyFunc( void ){ return MyFuncA(); }

0
Reply ram (2839) 5/30/2012 11:49:27 AM

On Wednesday, May 30, 2012 11:34:13 AM UTC+1, Malcolm McLean wrote:
> =D7=91=D7=AA=D7=90=D7=A8=D7=99=D7=9A =D7=99=D7=95=D7=9D =D7=A8=D7=91=D7=
=99=D7=A2=D7=99, 30 =D7=91=D7=9E=D7=90=D7=99 2012 10:50:10 UTC+1, =D7=9E=D7=
=90=D7=AA Ian Collins:
> > On 05/30/12 05:44 PM, mike3 wrote:

> > > I've got some stuff that looks like this:
> > >
> > > ---
> > > ErrorCode MyFunc()
> > > {
> > >            BigNum a, b, c, d;
> > >            ErrorCode rv;
> > >
> > >            rv =3D BigNum_Initialize(&a);
> > >            if(rv !=3D ERROR_SUCCESS)
> > >              return(rv);
> > >
> > >            rv =3D BigNum_Initialize(&b);
> > >            if(rv !=3D ERROR_SUCCESS)
> > >            {
> > >              BigNum_Free(&a); /* and what if THIS fails??? :) */
> > >              return(rv);
> > >            }
> >
> > I know I'm inviting flames, but this really is a classic case where C++=
=20
> > if you have access to it can be used as a better C....

I was tempted to say the same. Exceptiosn and RAII should be able to make i=
t quite tidy.

> You want
>=20
> rv =3D BigNum_Initilaize(&a);
> if(rv)
>   goto error_exit;
> rv =3D BigNum_Add(&a, &b, &c);
> if(!rv)
>    goto error_exit;
>=20
> it's slightly messier than exceptions, but unlike exceptions it's easier =
to test and harder to abuse.

why?

> You don't want to be defining the symbol,ERROR_SUCCESS in a bignum.h head=
er,

why? It's part of the Bignum interface.

> and you don't want bignum.c dependent on myerrorcodes.h.=20

ditto

> However -1 for out of memory is pretty standard.

I'd rather use a named constant... (I only recently found out this was a co=
ntroversial opinion!)

0
Reply nick_keighley_nospam (4575) 5/30/2012 11:53:56 AM

ram@zedat.fu-berlin.de (Stefan Ram) writes:
>mike3 <mike4ty4@yahoo.com> writes:
>>be done to relieve this code duplication? It's ugly, it hurts my
>The code below still has some duplication. I might write another
>post later with less duplication.

/* This general function can be put in a library */
static ErrorCode BigNum_New
( ErrorCode( *continuation )( void const * data, BigNum * const num ),
  void * data )
{ BigNum n;
  ErrorCode rv = BigNum_Initialize( &n );
  if( rv == ERROR_SUCCESS )
  { rv = continuation( data, &n ); BigNum_Free( &n ); }
  return rv; }

/* here the application code starts */
struct BigNum { BigNum * a; BigNum * b; BigNum * c; BigNum * d; };

static ErrorCode MyFuncX( void const * this )
{ return BigNum_Set( &((( struct BigNum * )this )->b ), 3 ); }

static ErrorCode MyFuncD( void const * this, BigNum * const num )
{ (( struct BigNum * )this )->d = num; return BigNum_New( MyFuncX, &this ); }

static ErrorCode MyFuncC( void const * this, BigNum * const num )
{ (( struct BigNum * )this )->c = num; return BigNum_New( MyFuncD, &this ); }

static ErrorCode MyFuncB( void const * this, BigNum * const num )
{ (( struct BigNum * )this )->b = num; return BigNum_New( MyFuncC, &this ); }

static ErrorCode MyFuncA( void const * this, BigNum * const num )
{ (( struct BigNum * )this )->a = num; return BigNum_New( MyFuncB, &this ); }

ErrorCode MyFunc( void )
{ struct BigNum this; return BigNum_New( MyFuncA, &this ); }

0
Reply ram (2839) 5/30/2012 12:09:05 PM

On May 30, 5:18=A0am, Willem <wil...@toad.stack.nl> wrote:
> If you want to be more concise, you can make ERROR_SUCCESS equal 0,
> and then you can simply do:
>
> =A0 =A0 rv =3D BigNum_Initialize(&a) || ... || BigNum_Set(&b, 3) || BigNu=
m_AddTo(&a, &b) || ... ;
>
> Which will short-circuit at the first failure.

Which in a sufficiently complicated function like an ECC point add/
double would result in spaghetti code and your termination.  :-)

The "if (err =3D=3D OK) ..." method is cool but frankly I just like the
goto's when I'm writing out something the long way.

Tom
0
Reply tom236 (284) 5/30/2012 12:16:55 PM

"mike3" <mike4ty4@yahoo.com> wrote in message
news:7e54cf3c-d514-407b-a9b6-c0009589d242@ra8g2000pbc.googlegroups.com...

> ErrorCode MyFunc()
> {
>          BigNum a, b, c, d;
>          ErrorCode rv;
>
>          rv = BigNum_Initialize(&a);
>          if(rv != ERROR_SUCCESS)
>            return(rv);

<etc>

> But this is nasty, with all those duplicated "free" blocks. What can
> be done to relieve this code duplication? It's ugly, it hurts my
> freaking eyes and my nose is screaming for relief. And it hurts
> maintainability to no end -- what if we decide to add more capability
> to MyFunc() that requires additional bignums? Oy... We'd have to
> update _all those blocks_.

I think you've designed in too much error-checking, and made your bignums
unwieldy to initialise and manage.

Any code trying to actually do something with bignums would be lost amongst
all the error-checking and recovery. And if there was some conditional code,
and every single calculation needed checking, then you would easily lose
track of what needed freeing and what didn't.

Why does an initialisation need error-checking anyway? Does it involve
allocating memory?

It's not clear if a bignum is a pointer or a struct; they could be simply
initialised to NULL or to {0}, leaving it to the bignum arithmetic routines
to allocate as needed, and do the error-checking. Your code might still need
to free, but the free routine can leave alone bignums that are still NULL or
{0}.

Actually, for memory management, you should take seriously the idea put
forward of using garbage collection. Then you don't need to explicitly free
memory.

> ErrorCode MyFunc()
> {
>          BigNum a, b, c, d;
>          ErrorCode rv;
>
>          rv = BigNum_Initialize(&a); if(rv != ERROR_SUCCESS) goto
> fail0;
>          rv = BigNum_Initialize(&b); if(rv != ERROR_SUCCESS) goto
> fail1;
>          rv = BigNum_Initialize(&c); if(rv != ERROR_SUCCESS) goto
> fail2;
>          rv = BigNum_Initialize(&d); if(rv != ERROR_SUCCESS) goto
> fail3;

(As a personal preference, I would use something like BN_Init(). Then these
big names would dominate the code so much.)

And, whatever the initialisation does, is it really necessary to check the
result? Why not leave it to routines such as BigNum_Set() to validate it's
arguments; if an argument has not been properly initialised, then *it*
returns a failure code.

>
>          /* do some math */
>          rv = BigNum_Set(&b, 3); if(rv != ERROR_SUCCESS) goto fail4;
>
>          ...
>
>          /* free buffers */
>          rv = BigNum_Free(&d); if(rv != ERROR_SUCCESS) goto fail3;

And what is likely to go wrong with BigNum_Free() that will need checking?
Will the caller of this function care, provided it gets the right answer? Or
is the result of BigNum_Set() likely to be invalidated if a subsequent free
fails?

>          rv = BigNum_Free(&c); if(rv != ERROR_SUCCESS) goto fail2;
>          rv = BigNum_Free(&b); if(rv != ERROR_SUCCESS) goto fail1;
>          rv = BigNum_Free(&a); if(rv != ERROR_SUCCESS) goto fail0;
>
>          return(ERROR_SUCCESS);
>
> fail4:    BigNum_Free(&d);
> fail3:    BigNum_Free(&c);
> fail2:    BigNum_Free(&b);
> fail1:    BigNum_Free(&a);
> fail0:    return(rv);
> }

If you do need to do this, then just combine all the statuses of multiple
calls to BigNum_Free() (the error code needs to be of a format that will
allow | or & operations).

I know your post is about managing error recovery, rather than the merits of
a particular library. But, someone needing to do arithmetic via function
calls, might prefer to keep error-checking low-key, perhaps something like
this:

ErrorCode BigNum_Average(BigNum A, BigNum B, BigNum Result) {
BigNum Two=NULL;
ErrorCode e=0;

 e |= BigNum_Add(A,B, Result);
 e |= BigNum_Set(&Two, 2);
 e |= BigNum_Div(Result, Two, Result);

 e |= BigNum_Free(&Two);

 return e;
}

Then it is still reasonably easy to follow what's going on. (Actually, I 
wouldn't bother with the error codes myself; I would build a status into the 
bignum itself, a bit like the Nans of floating point.)

-- 
Bartc 

0
Reply bc (2221) 5/30/2012 12:28:44 PM

ram@zedat.fu-berlin.de (Stefan Ram) writes:
>ram@zedat.fu-berlin.de (Stefan Ram) writes:
>>mike3 <mike4ty4@yahoo.com> writes:
>>>be done to relieve this code duplication? It's ugly, it hurts my
>>The code below still has some duplication. I might write another
>>post later with less duplication.
>/* This general function can be put in a library */

  The next variant is less clean/general due to object
  identifiers with file scope, but the �application code�
  now is as concise as possible.

/* This general function can be put away into a library */
ErrorCode BigNum_New
( ErrorCode( *continuation )( void ), BigNum * const n )
{ ErrorCode rv = BigNum_Initialize( &n );
  if( rv == ERROR_SUCCESS )
  { rv = continuation(); BigNum_Free( &n ); }
  return rv; }

/* here the application code starts */
static BigNum a; static BigNum b; static BigNum c; static BigNum d;
static ErrorCode MyFuncX( void ){ return BigNum_Set( &b, 3 ); }
static ErrorCode MyFuncD( void ){ return BigNum_New( MyFuncX, &d ); }
static ErrorCode MyFuncC( void ){ return BigNum_New( MyFuncD, &c ); }
static ErrorCode MyFuncB( void ){ return BigNum_New( MyFuncC, &b ); }
ErrorCode MyFunc( void ){ return BigNum_New( MyFuncB, &a ); }

0
Reply ram (2839) 5/30/2012 12:39:29 PM

ram@zedat.fu-berlin.de (Stefan Ram) writes:
>( ErrorCode( *continuation )( void ), BigNum * const n )
>{ ErrorCode rv = BigNum_Initialize( &n );
>  if( rv == ERROR_SUCCESS )
>  { rv = continuation(); BigNum_Free( &n ); }

  Oops, I think �&n� should become �n� above.

0
Reply ram (2839) 5/30/2012 12:42:51 PM

ram@zedat.fu-berlin.de (Stefan Ram) writes:
>ram@zedat.fu-berlin.de (Stefan Ram) writes:
>>ram@zedat.fu-berlin.de (Stefan Ram) writes:
>>>mike3 <mike4ty4@yahoo.com> writes:
>>>>be done to relieve this code duplication? It's ugly, it hurts my
>>>The code below still has some duplication. I might write another
>>>post later with less duplication.
>>/* This general function can be put in a library */
>The next variant is less clean/general due to object
>identifiers with file scope, but the �application code�
>now is as concise as possible.

  In this special case, it can be made a little more concise:

/* This general function can be put away into a library */
/* (unchanged since the last post, except for an error correction) */
ErrorCode BigNum_New
( ErrorCode( *continuation )( void ), BigNum * const n )
{ ErrorCode rv = BigNum_Initialize( n );
  if( rv == ERROR_SUCCESS )
  { rv = continuation(); BigNum_Free( n ); }
  return rv; }

/* here the application code starts */
static BigNum a[ 4 ]; static int i; static ErrorCode MyFuncX()
{ return i < 4 ? BigNum_New( MyFuncX, a + i++ ): BigNum_Set( a + 1, 3 ); }
ErrorCode MyFunc( void ){ i = 0; return MyFuncX(); }

0
Reply ram (2839) 5/30/2012 1:05:37 PM

"mike3" <mike4ty4@yahoo.com> ha scritto nel messaggio
news:7e54cf3c-d514-407b-a9b6-c0009589d242@ra8g2000pbc.googlegroups.com...
> Hi.
>
> I've got some stuff that looks like this:

this is my way...

ErrorCode MyFunc(void)
{BigNum a, b, c, d;
 ErrorCode  rv, rk;

 if((rv=BigNum_Initialize(&a))!= ERROR_SUCCESS)
                             return  rv;
 if((rv = BigNum_Initialize(&b)) != ERROR_SUCCESS)
    {ex1:   BigNum_Free(&a); return  rv;}
 if((rv = BigNum_Initialize(&c)) != ERROR_SUCCESS)
    {ex2:   BigNum_Free(&b); goto   ex1;}
 if((rv = BigNum_Initialize(&d)) != ERROR_SUCCESS)
    {ex3:   BigNum_Free(&c); goto   ex2;}
 if((rv = BigNum_Set(&b, 3))     != ERROR_SUCCESS)
    {ex4:   BigNum_Free(&d); goto   ex3;}
          ...
          /* free buffers */
 rv=ERROR_SUCCESS;
 if((rk=BigNum_Free(&d))!=ERROR_SUCCESS)  rv=rk;
 if((rk=BigNum_Free(&c))!=ERROR_SUCCESS)  rv=rk;
 if((rk=BigNum_Free(&b))!=ERROR_SUCCESS)  rv=rk;
 if((rk=BigNum_Free(&a))!=ERROR_SUCCESS)  rv=rk;
 return rv;
}


> But this is nasty, with all those duplicated "free" blocks. What can
> be done to relieve this code duplication? It's ugly, it hurts my
> freaking eyes and my nose is screaming for relief. And it hurts
> maintainability to no end -- what if we decide to add more capability
> to MyFunc() that requires additional bignums? Oy... We'd have to
> update _all those blocks_.
>
> I was thinking about using a "goto", but Gotos are Bad, aren't they? I
> can't believe I may have to use a goto! What about Djikstra's famous
> letter? Is it possible that perhaps a goto may be GOOD here? Because
> with a goto this would all seem much simpler. If we violate Djikstra,
> we get:
>
> ---
>
> ErrorCode MyFunc()
> {
>          BigNum a, b, c, d;
>          ErrorCode rv;
>
>          rv = BigNum_Initialize(&a); if(rv != ERROR_SUCCESS) goto
> fail0;
>          rv = BigNum_Initialize(&b); if(rv != ERROR_SUCCESS) goto
> fail1;
>          rv = BigNum_Initialize(&c); if(rv != ERROR_SUCCESS) goto
> fail2;
>          rv = BigNum_Initialize(&d); if(rv != ERROR_SUCCESS) goto
> fail3;
>
>          /* do some math */
>          rv = BigNum_Set(&b, 3); if(rv != ERROR_SUCCESS) goto fail4;
>
>          ...
>
>          /* free buffers */
>          rv = BigNum_Free(&d); if(rv != ERROR_SUCCESS) goto fail3;

if above fail you not free c, b and a...

>          rv = BigNum_Free(&c); if(rv != ERROR_SUCCESS) goto fail2;
>          rv = BigNum_Free(&b); if(rv != ERROR_SUCCESS) goto fail1;
>          rv = BigNum_Free(&a); if(rv != ERROR_SUCCESS) goto fail0;
>
>          return(ERROR_SUCCESS);
>
> fail4:    BigNum_Free(&d);
> fail3:    BigNum_Free(&c);
> fail2:    BigNum_Free(&b);
> fail1:    BigNum_Free(&a);
> fail0:    return(rv);
> }



0
Reply io_x 5/30/2012 1:19:26 PM

On 2012-05-30, mike3 <mike4ty4@yahoo.com> wrote:
> I was thinking about using a "goto", but Gotos are Bad, aren't they? I
> can't believe I may have to use a goto! What about Djikstra's famous
> letter? Is it possible that perhaps a goto may be GOOD here? Because
> with a goto this would all seem much simpler. If we violate Djikstra,
> we get:

The name is Dijkstra, not Djikstra.
0
Reply ike7 (162) 5/30/2012 1:56:45 PM

On May 30, 1:44=A0am, mike3 <mike4...@yahoo.com> wrote:
> Hi.
>
> I've got some stuff that looks like this:
>
> ---
> ErrorCode MyFunc()
> {
> =A0 =A0 =A0 =A0 =A0 BigNum a, b, c, d;
> =A0 =A0 =A0 =A0 =A0 ErrorCode rv;
>
> =A0 =A0 =A0 =A0 =A0 rv =3D BigNum_Initialize(&a);
> =A0 =A0 =A0 =A0 =A0 if(rv !=3D ERROR_SUCCESS)
> =A0 =A0 =A0 =A0 =A0 =A0 return(rv);
>
> =A0 =A0 =A0 =A0 =A0 rv =3D BigNum_Initialize(&b);
> =A0 =A0 =A0 =A0 =A0 if(rv !=3D ERROR_SUCCESS)
> =A0 =A0 =A0 =A0 =A0 {
> =A0 =A0 =A0 =A0 =A0 =A0 BigNum_Free(&a); /* and what if THIS fails??? :) =
*/
> =A0 =A0 =A0 =A0 =A0 =A0 return(rv);
> =A0 =A0 =A0 =A0 =A0 }
>
> =A0 =A0 =A0 =A0 =A0 rv =3D BigNum_Initialize(&c);
> =A0 =A0 =A0 =A0 =A0 if(rv !=3D ERROR_SUCCESS)
> =A0 =A0 =A0 =A0 =A0 {
> =A0 =A0 =A0 =A0 =A0 =A0 BigNum_Free(&b);
> =A0 =A0 =A0 =A0 =A0 =A0 BigNum_Free(&a);
> =A0 =A0 =A0 =A0 =A0 =A0 return(rv);
> =A0 =A0 =A0 =A0 =A0 }
>
> =A0 =A0 =A0 =A0 =A0 rv =3D BigNum_Initialize(&d);
> =A0 =A0 =A0 =A0 =A0 if(rv !=3D ERROR_SUCCESS)
> =A0 =A0 =A0 =A0 =A0 {
> =A0 =A0 =A0 =A0 =A0 =A0 BigNum_Free(&c);
> =A0 =A0 =A0 =A0 =A0 =A0 BigNum_Free(&b);
> =A0 =A0 =A0 =A0 =A0 =A0 BigNum_Free(&a);
> =A0 =A0 =A0 =A0 =A0 =A0 return(rv);
> =A0 =A0 =A0 =A0 =A0 }
>
> =A0 =A0 =A0 =A0 =A0 /* do some math */
> =A0 =A0 =A0 =A0 =A0 rv =3D BigNum_Set(&b, 3);
> =A0 =A0 =A0 =A0 =A0 if(rv !=3D ERROR_SUCCESS)
> =A0 =A0 =A0 =A0 =A0 {
> =A0 =A0 =A0 =A0 =A0 =A0 BigNum_Free(&d);
> =A0 =A0 =A0 =A0 =A0 =A0 BigNum_Free(&c);
> =A0 =A0 =A0 =A0 =A0 =A0 BigNum_Free(&b);
> =A0 =A0 =A0 =A0 =A0 =A0 BigNum_Free(&a);
> =A0 =A0 =A0 =A0 =A0 =A0 return(rv);
> =A0 =A0 =A0 =A0 =A0 }
>
> =A0 =A0 =A0 =A0 =A0 ...
>
> =A0 =A0 =A0 =A0 =A0 /* free buffers */
> =A0 =A0 =A0 =A0 =A0 rv =3D BigNum_Free(&d);
> =A0 =A0 =A0 =A0 =A0 if(rv !=3D ERROR_SUCCESS)
> =A0 =A0 =A0 =A0 =A0 {
> =A0 =A0 =A0 =A0 =A0 =A0 BigNum_Free(&c);
> =A0 =A0 =A0 =A0 =A0 =A0 BigNum_Free(&b);
> =A0 =A0 =A0 =A0 =A0 =A0 BigNum_Free(&a);
> =A0 =A0 =A0 =A0 =A0 =A0 return(rv);
> =A0 =A0 =A0 =A0 =A0 }
>
> =A0 =A0 =A0 =A0 =A0 rv =3D BigNum_Free(&c);
> =A0 =A0 =A0 =A0 =A0 if(rv !=3D ERROR_SUCCESS)
> =A0 =A0 =A0 =A0 =A0 {
> =A0 =A0 =A0 =A0 =A0 =A0 BigNum_Free(&b);
> =A0 =A0 =A0 =A0 =A0 =A0 BigNum_Free(&a);
> =A0 =A0 =A0 =A0 =A0 =A0 return(rv);
> =A0 =A0 =A0 =A0 =A0 }
>
> =A0 =A0 =A0 =A0 =A0 rv =3D BigNum_Free(&b);
> =A0 =A0 =A0 =A0 =A0 if(rv !=3D ERROR_SUCCESS)
> =A0 =A0 =A0 =A0 =A0 {
> =A0 =A0 =A0 =A0 =A0 =A0 BigNum_Free(&a);
> =A0 =A0 =A0 =A0 =A0 =A0 return(rv);
> =A0 =A0 =A0 =A0 =A0 }
>
> =A0 =A0 =A0 =A0 =A0 rv =3D BigNum_Free(&a);
> =A0 =A0 =A0 =A0 =A0 if(rv !=3D ERROR_SUCCESS)
> =A0 =A0 =A0 =A0 =A0 =A0 return(rv);
>
> =A0 =A0 =A0 =A0 =A0 return(ERROR_SUCCESS);}
>
> ---

ErrorCode MyFunc()
{
          BigNum a, b, c, d;
          ErrorCode rv;

          rv =3D BigNum_Initialize(&a);
          rv =3D rv =3D=3D ERROR_SUCCESS ? BigNum_Initialize(&b) : rv;
          rv =3D rv =3D=3D ERROR_SUCCESS ? BigNum_Initialize(&c) : rv;
          rv =3D rv =3D=3D ERROR_SUCCESS ? BigNum_Initialize(&d) : rv;

          if (rv !=3D ERROR_SUCCESS)
          {
            BigNum_Free(&d);
            BigNum_Free(&c);
            BigNum_Free(&b);
            BigNum_Free(&a);
          }

          return(rv);
}
\endcode

The main issue with this style is that it assumes that BigNum_Free
operates like 'free' where a NULL pointer is a no-op.  If you can
initialize your BigNum variables to a corresponding "NULL" BigNum
state, and BigNum_Free interprets a "NULL" BigNum as a no-op, you can
duplicate this style.  You may need to add a distinct struct
initializer to your variable declarations if BigNum is not a pointer.

\code
/* Define an initialize macro to create a "NULL" BigNum */
#define BIGNUM_NULL_INIT { 0, NULL, ... }

BigNum a =3D BIGNUM_NULL_INIT;
BigNum b =3D BIGNUM_NULL_INIT;
BigNum c =3D BIGNUM_NULL_INIT;
BigNum d =3D BIGNUM_NULL_INIT;
\endcode

On a side note, the term ERROR_SUCCESS appears contradictory to me.  I
would prefer something like NO_ERROR or SUCCESS if you had control
over the error definitions.

Best regards,
John D.
0
Reply jadill33 (201) 5/30/2012 2:13:11 PM

On Wednesday, May 30, 2012 9:55:55 AM UTC+1, MarkBluemel wrote:
> On 05/30/2012 06:44 AM, mike3 wrote:
> 
> > But we've violated Djikstra and we've used a "bad" goto. How would
> > _you_ write MyFunc() above?
> 
> I personally don't like the infinitely indented if approach...

nor me. Even goto is cleaner.


0
Reply nick_keighley_nospam (4575) 5/30/2012 2:25:58 PM

mike3 <mike4ty4@yahoo.com> writes:

> I've got some stuff that looks like this:
<snip code>

Just because no one has yet used an array:

  ErrorCode MyFunc(void)
  {
       enum { a, b, c, d, n_big_nums };
       BigNum num[n_big_nums];
       ErrorCode rv;
   
       int n = 0;
       while (n < n_big_nums && BigNum_Initialize(&num[n]) == ERROR_SUCCESS)
            n++;
   
       if (n == n_big_nums)
            do {
                 /* do some math */
                 rv = BigNum_Set(&num[b], 3);
                 if (rv != ERROR_SUCCESS)
                      break;
                 /* ... */
            } while (0);
   
       while (n--)
            BigNum_Free(&num[n]);
       return rv;
  }

You don't have to use the do { ... } while (0); thing.  Just add a label
to the end loop and goto it instead of using break.

You have to switch a, b and so on to num[a], num[b] but it does extend
easily if you find you need another BigNum.

(Note that "ErrorCode MyFunc(void)" is a prototype whereas "ErrorCode
MyFunc()" is not.)

<snip>
-- 
Ben.
0
Reply ben.usenet (6516) 5/30/2012 3:37:42 PM

tom st denis wrote:
) On May 30, 5:18?am, Willem <wil...@toad.stack.nl> wrote:
)> If you want to be more concise, you can make ERROR_SUCCESS equal 0,
)> and then you can simply do:
)>
)> ? ? rv = BigNum_Initialize(&a) || ... || BigNum_Set(&b, 3) || BigNum_AddTo(&a, &b) || ... ;
)>
)> Which will short-circuit at the first failure.
)
) Which in a sufficiently complicated function like an ECC point add/
) double would result in spaghetti code and your termination.  :-)

How can it be spaghetti when it's a single line of calls, one after
the other?  Spaghetti code is meant to be tangled, isn't it?

) The "if (err == OK) ..." method is cool but frankly I just like the
) goto's when I'm writing out something the long way.

I've seen the (err == OK) method used too much in code that didn't require
cleanup at end of function.  Apparently somebody at our company believes in
'one-function-one-return' religiously.  I agree gotos are better.


Another method is to have all 'bignum' functions check for 'error' inputs
and generate 'error' outputs when they encounter them (or whenever they
 encounter an error), and then you only have to check for an 'error'
result at the very end.

Something like:

int DoCalc()
{
  int rv;
  BigNum a;
  BigNum b;
  BigNum c;
  BigNum d;

  BigNum_Init(&a);
  BigNum_Init(&b);
  BigNum_Init(&c);
  BigNum_Init(&d);

  BigNum_Set(&a, 3);
  BigNum_Set(&b, 5);
  ...
  BigNum_Multiply(&c, &d);
  ...
  if ((rv = BigNum_GetError(&d)) != ERROR_SUCCESS) return rv;

  BigNum_Print("The result is: %bn", &d);
  BigNum_Free(&a);
  BigNum_Free(&b);
  BigNum_Free(&c);
  BigNum_Free(&d);

  return ERROR_SUCCESS;
}

The only weirdside to this is when a value is not used in the final result,
then that value will not be checked for errors.


SaSW, Willem
-- 
Disclaimer: I am in no way responsible for any of the statements
            made in the above text. For all I know I might be
            drugged or something..
            No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
0
Reply willem6 (255) 5/30/2012 4:26:47 PM

mike3 wrote:
[...]
> But we've violated Djikstra and we've used a "bad" goto. How would
> _you_ write MyFunc() above?

Hello,

If you want to get rid of the gotos and the ifs, you might end up using 
some kind of object stack. Every time you create or initialize 
something, you push a handle and a destructor onto the stack. If 
something goes wrong, you work your way down the stack destroying all 
the resources. A bit like pthread_cleanup_push/pop. Of course it is 
kludgy, may involve unsafe casts and a bit of additional overhead. I do 
not use it much myself.

There is an implementation here:
http://members.aon.at/~aklamme4/dvbv/dvbvulture_1.0.23.tar.gz
In the files common/custck.c include/custck.h

(please ignore the code smell)

JK
0
Reply klammerj (96) 5/30/2012 5:05:41 PM

On May 30, 6:28=A0am, "BartC" <b...@freeuk.com> wrote:
> "mike3" <mike4...@yahoo.com> wrote in message
<snip>
> I think you've designed in too much error-checking, and made your bignums
> unwieldy to initialise and manage.
>
> Any code trying to actually do something with bignums would be lost among=
st
> all the error-checking and recovery. And if there was some conditional co=
de,
> and every single calculation needed checking, then you would easily lose
> track of what needed freeing and what didn't.
>
> Why does an initialisation need error-checking anyway? Does it involve
> allocating memory?
>

Yes. You have to allocate memory to initialize (for the buffer holding
the
bignum's digits.). And that can fail. Thus, I return an error code.

> It's not clear if a bignum is a pointer or a struct; they could be simply
> initialised to NULL or to {0}, leaving it to the bignum arithmetic routin=
es
> to allocate as needed, and do the error-checking. Your code might still n=
eed
> to free, but the free routine can leave alone bignums that are still NULL=
 or
> {0}.
>
> Actually, for memory management, you should take seriously the idea put
> forward of using garbage collection. Then you don't need to explicitly fr=
ee
> memory.
>
> > ErrorCode MyFunc()
> > {
> > =A0 =A0 =A0 =A0 =A0BigNum a, b, c, d;
> > =A0 =A0 =A0 =A0 =A0ErrorCode rv;
>
> > =A0 =A0 =A0 =A0 =A0rv =3D BigNum_Initialize(&a); if(rv !=3D ERROR_SUCCE=
SS) goto
> > fail0;
> > =A0 =A0 =A0 =A0 =A0rv =3D BigNum_Initialize(&b); if(rv !=3D ERROR_SUCCE=
SS) goto
> > fail1;
> > =A0 =A0 =A0 =A0 =A0rv =3D BigNum_Initialize(&c); if(rv !=3D ERROR_SUCCE=
SS) goto
> > fail2;
> > =A0 =A0 =A0 =A0 =A0rv =3D BigNum_Initialize(&d); if(rv !=3D ERROR_SUCCE=
SS) goto
> > fail3;
>
> (As a personal preference, I would use something like BN_Init(). Then the=
se
> big names would dominate the code so much.)
>
> And, whatever the initialisation does, is it really necessary to check th=
e
> result? Why not leave it to routines such as BigNum_Set() to validate it'=
s
> arguments; if an argument has not been properly initialised, then *it*
> returns a failure code.
>

What do you do with that failure code? :) See, you still need a
handler around
every math routine call. This would help with the Init() functions'
handlers, though.

>
>
> > =A0 =A0 =A0 =A0 =A0/* do some math */
> > =A0 =A0 =A0 =A0 =A0rv =3D BigNum_Set(&b, 3); if(rv !=3D ERROR_SUCCESS) =
goto fail4;
>
> > =A0 =A0 =A0 =A0 =A0...
>
> > =A0 =A0 =A0 =A0 =A0/* free buffers */
> > =A0 =A0 =A0 =A0 =A0rv =3D BigNum_Free(&d); if(rv !=3D ERROR_SUCCESS) go=
to fail3;
>
> And what is likely to go wrong with BigNum_Free() that will need checking=
?
> Will the caller of this function care, provided it gets the right answer?=
 Or
> is the result of BigNum_Set() likely to be invalidated if a subsequent fr=
ee
> fails?
>

Looking at the free function, it can return one error code:
ERROR_INVALID_STORAGE_TYPE. A bignum can be stored on either
memory or on disk (disk not yet implemented, but the stuff is there to
allow
for its implementation). There is, of course, a field in the bignum
that indicates
which is being used. If this is something weird -- something other
than
"memory" or "disk", then the "Free" function would get confused as it
wouldn't know how to properly free the bignum. Normally, that
shouldn't
happen. But if someone was doing something silly, the catch is there
to catch that. So, should I just remove that error return and say,
"well,
if you're messing around with this in some improper fashion, then
expect things to break"? But then we run into the problem of where
the field is corrupted due to a memory bug. In this case, a fail could
be useful (although one of the other bignum routines could puke as
well.).

An idea I had is to drop the type field altogether and use
something like this:

typedef struct BigNum {
....
     Digit *RAMBuffer;
     FILE *DiskBuffer;
....
} BigNum;

and when BigNum is initialized to RAM storage, RAMBuffer holds a ptr,
and DiskBuffer is NULL, and when BigNum is initialized to Disk
storage,
RAMBuffer is NULL, and DiskBuffer holds a ptr. Then there's no field
that
can get an invalid value, and if someone tries to set the NULL ptrs
to something else, then expect things to break. (If a ptr gets
corrupted,
you're pretty screwed anyway and there isn't much you can do about it)

> > =A0 =A0 =A0 =A0 =A0rv =3D BigNum_Free(&c); if(rv !=3D ERROR_SUCCESS) go=
to fail2;
> > =A0 =A0 =A0 =A0 =A0rv =3D BigNum_Free(&b); if(rv !=3D ERROR_SUCCESS) go=
to fail1;
> > =A0 =A0 =A0 =A0 =A0rv =3D BigNum_Free(&a); if(rv !=3D ERROR_SUCCESS) go=
to fail0;
>
> > =A0 =A0 =A0 =A0 =A0return(ERROR_SUCCESS);
>
> > fail4: =A0 =A0BigNum_Free(&d);
> > fail3: =A0 =A0BigNum_Free(&c);
> > fail2: =A0 =A0BigNum_Free(&b);
> > fail1: =A0 =A0BigNum_Free(&a);
> > fail0: =A0 =A0return(rv);
> > }
>
> If you do need to do this, then just combine all the statuses of multiple
> calls to BigNum_Free() (the error code needs to be of a format that will
> allow | or & operations).
>

The thing here is, that I have a general "universal" list of error
codes, numbered
0 (=3D success), 1, 2, 3, etc. and functions take their return codes
from that.
Perhaps that's not the best way to do it? (I was inspired by
Microsoft's Windows
system with all its error codes.) E.g. we could use for the bignum
routines
a special set of 32-bit (or even 64-bit, in this case -- this program
is for 64-bit
systems anyway) error codes with at most 32 possible errors (probably
way more than'd be needed from a simple bignum routine!) error codes
that
indicate errors by bit flags (all zeroes =3D success), and could be ORed
together
to get what errors occurred in the code under consideration.

> I know your post is about managing error recovery, rather than the merits=
 of
> a particular library. But, someone needing to do arithmetic via function
> calls, might prefer to keep error-checking low-key, perhaps something lik=
e
> this:
>
> ErrorCode BigNum_Average(BigNum A, BigNum B, BigNum Result) {
> BigNum Two=3DNULL;
> ErrorCode e=3D0;
>
> =A0e |=3D BigNum_Add(A,B, Result);
> =A0e |=3D BigNum_Set(&Two, 2);
> =A0e |=3D BigNum_Div(Result, Two, Result);
>
> =A0e |=3D BigNum_Free(&Two);
>
> =A0return e;
>
> }
>
> Then it is still reasonably easy to follow what's going on. (Actually, I
> wouldn't bother with the error codes myself; I would build a status into =
the
> bignum itself, a bit like the Nans of floating point.)
>

Yes, a "NAN" or error flag is another possibility. Flag would be best
-- it's
real easy to check and you could set multiple values -- like 1 for bad
alloc,
2 for overflow, etc.
0
Reply mike4ty4 (405) 5/30/2012 8:57:35 PM

On May 30, 2:19=A0pm, "io_x" <a...@b.c.invalid> wrote:

> this is my way...

Why does this not surprise me?

> ErrorCode MyFunc(void)
> {BigNum a, b, c, d;
> =A0ErrorCode =A0rv, rk;
>
> =A0if((rv=3DBigNum_Initialize(&a))!=3D ERROR_SUCCESS)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0return =A0rv;
> =A0if((rv =3D BigNum_Initialize(&b)) !=3D ERROR_SUCCESS)
> =A0 =A0 {ex1: =A0 BigNum_Free(&a); return =A0rv;}
> =A0if((rv =3D BigNum_Initialize(&c)) !=3D ERROR_SUCCESS)
> =A0 =A0 {ex2: =A0 BigNum_Free(&b); goto =A0 ex1;}
> =A0if((rv =3D BigNum_Initialize(&d)) !=3D ERROR_SUCCESS)
> =A0 =A0 {ex3: =A0 BigNum_Free(&c); goto =A0 ex2;}
> =A0if((rv =3D BigNum_Set(&b, 3)) =A0 =A0 !=3D ERROR_SUCCESS)
> =A0 =A0 {ex4: =A0 BigNum_Free(&d); goto =A0 ex3;}

Ouch!
0
Reply mark.bluemel (71) 5/31/2012 8:10:14 AM

mike3 <mike4ty4@yahoo.com> writes:

> I've got some stuff that looks like this:
>
> ---
> ErrorCode MyFunc()
> {
>           BigNum a, b, c, d;
>           ErrorCode rv;
>
>           rv = BigNum_Initialize(&a);
>           if(rv != ERROR_SUCCESS)
>             return(rv);
>
>           rv = BigNum_Initialize(&b);
>           if(rv != ERROR_SUCCESS)
>           {
>             BigNum_Free(&a); /* and what if THIS fails??? :) */
>             return(rv);
>           }
>
>           rv = BigNum_Initialize(&c);
>           if(rv != ERROR_SUCCESS)
>           {
>             BigNum_Free(&b);
>             BigNum_Free(&a);
>             return(rv);
>           }
>
>           rv = BigNum_Initialize(&d);
>           if(rv != ERROR_SUCCESS)
>           {
>             BigNum_Free(&c);
>             BigNum_Free(&b);
>             BigNum_Free(&a);
>             return(rv);
>           }
>
>           /* do some math */
>           rv = BigNum_Set(&b, 3);
>           if(rv != ERROR_SUCCESS)
>           {
>             BigNum_Free(&d);
>             BigNum_Free(&c);
>             BigNum_Free(&b);
>             BigNum_Free(&a);
>             return(rv);
>           }
>
>           ...
>
>           /* free buffers */
>           rv = BigNum_Free(&d);
>           if(rv != ERROR_SUCCESS)
>           {
>             BigNum_Free(&c);
>             BigNum_Free(&b);
>             BigNum_Free(&a);
>             return(rv);
>           }
>
>           rv = BigNum_Free(&c);
>           if(rv != ERROR_SUCCESS)
>           {
>             BigNum_Free(&b);
>             BigNum_Free(&a);
>             return(rv);
>           }
>
>           rv = BigNum_Free(&b);
>           if(rv != ERROR_SUCCESS)
>           {
>             BigNum_Free(&a);
>             return(rv);
>           }
>
>           rv = BigNum_Free(&a);
>           if(rv != ERROR_SUCCESS)
>             return(rv);
>
>           return(ERROR_SUCCESS);
> }
> ---
>
> But this is nasty, with all those duplicated "free" blocks. What can
> be done to relieve this code duplication? It's ugly, it hurts my
> freaking eyes and my nose is screaming for relief. And it hurts
> maintainability to no end -- what if we decide to add more capability
> to MyFunc() that requires additional bignums? Oy... We'd have to
> update _all those blocks_.
>
> I was thinking about using a "goto", but Gotos are Bad, aren't they? I
> can't believe I may have to use a goto! What about Djikstra's famous
> letter? Is it possible that perhaps a goto may be GOOD here? Because
> with a goto this would all seem much simpler. If we violate Djikstra,
> we get:
>
> ---
>
> ErrorCode MyFunc()
> {
>           BigNum a, b, c, d;
>           ErrorCode rv;
>
>           rv = BigNum_Initialize(&a); if(rv != ERROR_SUCCESS) goto
> fail0;
>           rv = BigNum_Initialize(&b); if(rv != ERROR_SUCCESS) goto
> fail1;
>           rv = BigNum_Initialize(&c); if(rv != ERROR_SUCCESS) goto
> fail2;
>           rv = BigNum_Initialize(&d); if(rv != ERROR_SUCCESS) goto
> fail3;
>
>           /* do some math */
>           rv = BigNum_Set(&b, 3); if(rv != ERROR_SUCCESS) goto fail4;
>
>           ...
>
>           /* free buffers */
>           rv = BigNum_Free(&d); if(rv != ERROR_SUCCESS) goto fail3;
>           rv = BigNum_Free(&c); if(rv != ERROR_SUCCESS) goto fail2;
>           rv = BigNum_Free(&b); if(rv != ERROR_SUCCESS) goto fail1;
>           rv = BigNum_Free(&a); if(rv != ERROR_SUCCESS) goto fail0;
>
>           return(ERROR_SUCCESS);
>
> fail4:    BigNum_Free(&d);
> fail3:    BigNum_Free(&c);
> fail2:    BigNum_Free(&b);
> fail1:    BigNum_Free(&a);
> fail0:    return(rv);
> }
> ---
>
> But we've violated Djikstra and we've used a "bad" goto. How would
> _you_ write MyFunc() above?

Your question is really about style.  As is usually the case in
such matters, there are no right or wrong answers, just individual
preference, and perhaps local culture that should also be taken
into account.

That said, when a question like this comes up, usually it's a
strong indication that the program design is wrong at some
higher level.  If you find yourself writing lots of ugly
functions, there's a good chance it will be worth rethinking
some higher-level decisions and see if a different approach
leads to cleaner code at the function level.
0
Reply txr1 (1241) 5/31/2012 8:19:00 PM

On May 31, 2:19=A0pm, Tim Rentsch <t...@alumni.caltech.edu> wrote:
> mike3 <mike4...@yahoo.com> writes:
> > I've got some stuff that looks like this:
>
> > ---
> > ErrorCode MyFunc()
> > {
> > =A0 =A0 =A0 =A0 =A0 BigNum a, b, c, d;
> > =A0 =A0 =A0 =A0 =A0 ErrorCode rv;
>
> > =A0 =A0 =A0 =A0 =A0 rv =3D BigNum_Initialize(&a);
> > =A0 =A0 =A0 =A0 =A0 if(rv !=3D ERROR_SUCCESS)
> > =A0 =A0 =A0 =A0 =A0 =A0 return(rv);
>
> > =A0 =A0 =A0 =A0 =A0 rv =3D BigNum_Initialize(&b);
> > =A0 =A0 =A0 =A0 =A0 if(rv !=3D ERROR_SUCCESS)
> > =A0 =A0 =A0 =A0 =A0 {
> > =A0 =A0 =A0 =A0 =A0 =A0 BigNum_Free(&a); /* and what if THIS fails??? :=
) */
> > =A0 =A0 =A0 =A0 =A0 =A0 return(rv);
> > =A0 =A0 =A0 =A0 =A0 }
>
> > =A0 =A0 =A0 =A0 =A0 rv =3D BigNum_Initialize(&c);
> > =A0 =A0 =A0 =A0 =A0 if(rv !=3D ERROR_SUCCESS)
> > =A0 =A0 =A0 =A0 =A0 {
> > =A0 =A0 =A0 =A0 =A0 =A0 BigNum_Free(&b);
> > =A0 =A0 =A0 =A0 =A0 =A0 BigNum_Free(&a);
> > =A0 =A0 =A0 =A0 =A0 =A0 return(rv);
> > =A0 =A0 =A0 =A0 =A0 }
>
> > =A0 =A0 =A0 =A0 =A0 rv =3D BigNum_Initialize(&d);
> > =A0 =A0 =A0 =A0 =A0 if(rv !=3D ERROR_SUCCESS)
> > =A0 =A0 =A0 =A0 =A0 {
> > =A0 =A0 =A0 =A0 =A0 =A0 BigNum_Free(&c);
> > =A0 =A0 =A0 =A0 =A0 =A0 BigNum_Free(&b);
> > =A0 =A0 =A0 =A0 =A0 =A0 BigNum_Free(&a);
> > =A0 =A0 =A0 =A0 =A0 =A0 return(rv);
> > =A0 =A0 =A0 =A0 =A0 }
>
> > =A0 =A0 =A0 =A0 =A0 /* do some math */
> > =A0 =A0 =A0 =A0 =A0 rv =3D BigNum_Set(&b, 3);
> > =A0 =A0 =A0 =A0 =A0 if(rv !=3D ERROR_SUCCESS)
> > =A0 =A0 =A0 =A0 =A0 {
> > =A0 =A0 =A0 =A0 =A0 =A0 BigNum_Free(&d);
> > =A0 =A0 =A0 =A0 =A0 =A0 BigNum_Free(&c);
> > =A0 =A0 =A0 =A0 =A0 =A0 BigNum_Free(&b);
> > =A0 =A0 =A0 =A0 =A0 =A0 BigNum_Free(&a);
> > =A0 =A0 =A0 =A0 =A0 =A0 return(rv);
> > =A0 =A0 =A0 =A0 =A0 }
>
> > =A0 =A0 =A0 =A0 =A0 ...
>
> > =A0 =A0 =A0 =A0 =A0 /* free buffers */
> > =A0 =A0 =A0 =A0 =A0 rv =3D BigNum_Free(&d);
> > =A0 =A0 =A0 =A0 =A0 if(rv !=3D ERROR_SUCCESS)
> > =A0 =A0 =A0 =A0 =A0 {
> > =A0 =A0 =A0 =A0 =A0 =A0 BigNum_Free(&c);
> > =A0 =A0 =A0 =A0 =A0 =A0 BigNum_Free(&b);
> > =A0 =A0 =A0 =A0 =A0 =A0 BigNum_Free(&a);
> > =A0 =A0 =A0 =A0 =A0 =A0 return(rv);
> > =A0 =A0 =A0 =A0 =A0 }
>
> > =A0 =A0 =A0 =A0 =A0 rv =3D BigNum_Free(&c);
> > =A0 =A0 =A0 =A0 =A0 if(rv !=3D ERROR_SUCCESS)
> > =A0 =A0 =A0 =A0 =A0 {
> > =A0 =A0 =A0 =A0 =A0 =A0 BigNum_Free(&b);
> > =A0 =A0 =A0 =A0 =A0 =A0 BigNum_Free(&a);
> > =A0 =A0 =A0 =A0 =A0 =A0 return(rv);
> > =A0 =A0 =A0 =A0 =A0 }
>
> > =A0 =A0 =A0 =A0 =A0 rv =3D BigNum_Free(&b);
> > =A0 =A0 =A0 =A0 =A0 if(rv !=3D ERROR_SUCCESS)
> > =A0 =A0 =A0 =A0 =A0 {
> > =A0 =A0 =A0 =A0 =A0 =A0 BigNum_Free(&a);
> > =A0 =A0 =A0 =A0 =A0 =A0 return(rv);
> > =A0 =A0 =A0 =A0 =A0 }
>
> > =A0 =A0 =A0 =A0 =A0 rv =3D BigNum_Free(&a);
> > =A0 =A0 =A0 =A0 =A0 if(rv !=3D ERROR_SUCCESS)
> > =A0 =A0 =A0 =A0 =A0 =A0 return(rv);
>
> > =A0 =A0 =A0 =A0 =A0 return(ERROR_SUCCESS);
> > }
> > ---
>
> > But this is nasty, with all those duplicated "free" blocks. What can
> > be done to relieve this code duplication? It's ugly, it hurts my
> > freaking eyes and my nose is screaming for relief. And it hurts
> > maintainability to no end -- what if we decide to add more capability
> > to MyFunc() that requires additional bignums? Oy... We'd have to
> > update _all those blocks_.
>
> > I was thinking about using a "goto", but Gotos are Bad, aren't they? I
> > can't believe I may have to use a goto! What about Djikstra's famous
> > letter? Is it possible that perhaps a goto may be GOOD here? Because
> > with a goto this would all seem much simpler. If we violate Djikstra,
> > we get:
>
> > ---
>
> > ErrorCode MyFunc()
> > {
> > =A0 =A0 =A0 =A0 =A0 BigNum a, b, c, d;
> > =A0 =A0 =A0 =A0 =A0 ErrorCode rv;
>
> > =A0 =A0 =A0 =A0 =A0 rv =3D BigNum_Initialize(&a); if(rv !=3D ERROR_SUCC=
ESS) goto
> > fail0;
> > =A0 =A0 =A0 =A0 =A0 rv =3D BigNum_Initialize(&b); if(rv !=3D ERROR_SUCC=
ESS) goto
> > fail1;
> > =A0 =A0 =A0 =A0 =A0 rv =3D BigNum_Initialize(&c); if(rv !=3D ERROR_SUCC=
ESS) goto
> > fail2;
> > =A0 =A0 =A0 =A0 =A0 rv =3D BigNum_Initialize(&d); if(rv !=3D ERROR_SUCC=
ESS) goto
> > fail3;
>
> > =A0 =A0 =A0 =A0 =A0 /* do some math */
> > =A0 =A0 =A0 =A0 =A0 rv =3D BigNum_Set(&b, 3); if(rv !=3D ERROR_SUCCESS)=
 goto fail4;
>
> > =A0 =A0 =A0 =A0 =A0 ...
>
> > =A0 =A0 =A0 =A0 =A0 /* free buffers */
> > =A0 =A0 =A0 =A0 =A0 rv =3D BigNum_Free(&d); if(rv !=3D ERROR_SUCCESS) g=
oto fail3;
> > =A0 =A0 =A0 =A0 =A0 rv =3D BigNum_Free(&c); if(rv !=3D ERROR_SUCCESS) g=
oto fail2;
> > =A0 =A0 =A0 =A0 =A0 rv =3D BigNum_Free(&b); if(rv !=3D ERROR_SUCCESS) g=
oto fail1;
> > =A0 =A0 =A0 =A0 =A0 rv =3D BigNum_Free(&a); if(rv !=3D ERROR_SUCCESS) g=
oto fail0;
>
> > =A0 =A0 =A0 =A0 =A0 return(ERROR_SUCCESS);
>
> > fail4: =A0 =A0BigNum_Free(&d);
> > fail3: =A0 =A0BigNum_Free(&c);
> > fail2: =A0 =A0BigNum_Free(&b);
> > fail1: =A0 =A0BigNum_Free(&a);
> > fail0: =A0 =A0return(rv);
> > }
> > ---
>
> > But we've violated Djikstra and we've used a "bad" goto. How would
> > _you_ write MyFunc() above?
>
> Your question is really about style. =A0As is usually the case in
> such matters, there are no right or wrong answers, just individual
> preference, and perhaps local culture that should also be taken
> into account.
>
> That said, when a question like this comes up, usually it's a
> strong indication that the program design is wrong at some
> higher level. =A0If you find yourself writing lots of ugly
> functions, there's a good chance it will be worth rethinking
> some higher-level decisions and see if a different approach
> leads to cleaner code at the function level.

So what would the "bad design" be in this case? There doesn't
seem to be a whole lot of things that could be changed. A bignum
system will have init, free, and arithmetic routines. Trouble
seems to be due to the possibility of return codes on every
bignum operation. Is this the "design problem"? Notice that
something like, say, GMP, doesn't do that. All GMP functions
return void or an arithmetic result, not an error code. But I *do*
want to have some sort of error reporting functionality.
0
Reply mike4ty4 (405) 5/31/2012 8:49:08 PM

"mike3" <mike4ty4@yahoo.com> wrote in message
news:58595afa-412f-4ef0-b66e-bbad70698a2d@s6g2000pbi.googlegroups.com...
> On May 31, 2:19 pm, Tim Rentsch <t...@alumni.caltech.edu> wrote:

>> That said, when a question like this comes up, usually it's a
>> strong indication that the program design is wrong at some
>> higher level.  If you find yourself writing lots of ugly
>> functions, there's a good chance it will be worth rethinking
>> some higher-level decisions and see if a different approach
>> leads to cleaner code at the function level.
>
> So what would the "bad design" be in this case? There doesn't
> seem to be a whole lot of things that could be changed. A bignum
> system will have init, free, and arithmetic routines. Trouble
> seems to be due to the possibility of return codes on every
> bignum operation. Is this the "design problem"?

Sounds like it.

But whatever you end up doing, perhaps consider the possibility of having a
second set of functions that shadow the main ones (and which could wrap the
main functions).

These secondary functions take care of error-checking. Then the programmer
can do more productive work without worrying about errors 90% of the time.

Of course it depends on what sort of errors are likely; if they are rare,
and an abort (or one of those longjmps) is acceptable when there is a
problem, then this can be workable. But it is also up to the programmer
which set of functions to call.

It depends also how the code that uses this library fits into the overall
program; if this is just servicing something bigger, such as a language
runtime, then you don't want minor numeric problems to bring down the
system.

In any case, ignoring checking an errorcode shouldn't bring down the system 
either; but this could need *more* checking inside the library itself (which 
you may or may not have access to).

-- 
Bartc 

0
Reply bc (2221) 5/31/2012 9:08:02 PM

On May 31, 3:08=A0pm, "BartC" <b...@freeuk.com> wrote:
> "mike3" <mike4...@yahoo.com> wrote in message
>
> news:58595afa-412f-4ef0-b66e-bbad70698a2d@s6g2000pbi.googlegroups.com...
>
> > On May 31, 2:19 pm, Tim Rentsch <t...@alumni.caltech.edu> wrote:
> >> That said, when a question like this comes up, usually it's a
> >> strong indication that the program design is wrong at some
> >> higher level. =A0If you find yourself writing lots of ugly
> >> functions, there's a good chance it will be worth rethinking
> >> some higher-level decisions and see if a different approach
> >> leads to cleaner code at the function level.
>
> > So what would the "bad design" be in this case? There doesn't
> > seem to be a whole lot of things that could be changed. A bignum
> > system will have init, free, and arithmetic routines. Trouble
> > seems to be due to the possibility of return codes on every
> > bignum operation. Is this the "design problem"?
>
> Sounds like it.
>
> But whatever you end up doing, perhaps consider the possibility of having=
 a
> second set of functions that shadow the main ones (and which could wrap t=
he
> main functions).
>
> These secondary functions take care of error-checking. Then the programme=
r
> can do more productive work without worrying about errors 90% of the time=
..
>
> Of course it depends on what sort of errors are likely; if they are rare,
> and an abort (or one of those longjmps) is acceptable when there is a
> problem, then this can be workable. But it is also up to the programmer
> which set of functions to call.
>
> It depends also how the code that uses this library fits into the overall
> program; if this is just servicing something bigger, such as a language
> runtime, then you don't want minor numeric problems to bring down the
> system.
>
> In any case, ignoring checking an errorcode shouldn't bring down the syst=
em
> either; but this could need *more* checking inside the library itself (wh=
ich
> you may or may not have access to).
>
> --
> Bartc

However, some of these errors can't simply be ignored, like an "out of
memory"
error or "out of disk space" error. And it would also be a nice
feature to know
if something has gone wrong with the computation.
0
Reply mike4ty4 (405) 5/31/2012 11:08:46 PM

On May 29, 11:44=A0pm, mike3 <mike4...@yahoo.com> wrote:
<snip>

I've made an interesting and disturbing discovery.

I found THIS:

http://www.isc.org/software/bind/991

I decided to have a look at the source code, and oh my goodness! What
did I find?!
Oh NO....!!!!!!!!!!!!!!!!!!!!!!! :

----

idn_result_t
idn_normalizer_add(idn_normalizer_t ctx, const char *scheme_name) {
	idn_result_t r;
	void *v;
	normalize_scheme_t *scheme;

	assert(ctx !=3D NULL && scheme_name !=3D NULL);

	TRACE(("idn_normalizer_add(scheme_name=3D%s)\n", scheme_name));

	assert(INITIALIZED);

	if (idn__strhash_get(scheme_hash, scheme_name, &v) !=3D idn_success) {
		ERROR(("idn_normalizer_add(): invalid scheme \"%-.30s\"\n",
		       scheme_name));
		r =3D idn_invalid_name;
		goto ret;
<----------------- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!=
!!!!!!!
	}

	scheme =3D v;

	assert(ctx->nschemes <=3D ctx->scheme_size);

	if (ctx->nschemes =3D=3D ctx->scheme_size &&
	    (r =3D expand_schemes(ctx)) !=3D idn_success) {
		goto ret;
<----------------- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!=
!!!!!!!
	}

	ctx->schemes[ctx->nschemes++] =3D scheme;
	r =3D idn_success;
ret:
<----------------- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!=
!!!!!!!
	TRACE(("idn_normalizer_add(): %s\n", idn_result_tostring(r)));
	return (r);
}

----

YES, that's right -- those are GOTOs in there, and they do this a LOT
in this program! Djikstra!!!

But as this thread seems to show, it looks like that there exist
alternatives
to GOTO, and so we can still uphold Djikstra's law. Or is there
something
about this program that makes it OK to use GOTOs in it, but it is not
OK
to use them in the one I'm doing?
0
Reply mike4ty4 (405) 5/31/2012 11:39:28 PM

On May 29, 11:44=A0pm, mike3 <mike4...@yahoo.com> wrote:
<snip>

I've also noticed another problem. I've got a place where a
routine needs to _return_ a BigNum it mints inside itself.

ErrorCode MyFunc(BigNum **OutputValue)
{
          ...
          *OutputValue =3D (BigNum *)malloc(sizeof(BigNum));
          if(*OutputValue =3D=3D NULL)
            {
                <duplicated err handler>
            }

          rv =3D BigNum_Initialize(*OutputValue);
          if(rv !=3D ERROR_SUCCESS)
            {
                <ditto>
            }

          ...
          (error handlers in here that now have to _free the alloced
memory
          and not just deinit the BigNum_! What should I do about
this?)
          ...
}

What to do?
0
Reply mike4ty4 (405) 5/31/2012 11:46:40 PM

mike3 <mike4ty4@yahoo.com> writes:

> On May 31, 2:19 pm, Tim Rentsch <t...@alumni.caltech.edu> wrote:
>> mike3 <mike4...@yahoo.com> writes:
>> [snip]
>>
>> Your question is really about style.  As is usually the case in
>> such matters, there are no right or wrong answers, just individual
>> preference, and perhaps local culture that should also be taken
>> into account.
>>
>> That said, when a question like this comes up, usually it's a
>> strong indication that the program design is wrong at some
>> higher level.  If you find yourself writing lots of ugly
>> functions, there's a good chance it will be worth rethinking
>> some higher-level decisions and see if a different approach
>> leads to cleaner code at the function level.
>
> So what would the "bad design" be in this case?

To answer that question one would need both more specific information
and more context.  The example you gave was fairly limited and also
rather abstract.  Not saying there is anything wrong with that, there
isn't, but it doesn't provide enough information to answer the
followup question.

> There doesn't seem to be a whole lot of things that could be
> changed.  [snip elaboration]

Undoubtedly there are lots of things that can't be changed, but
unless the situation is very different from what I would expect there
still are lots of design choices available.  Maybe you have locked in
on some unconscious assumptions?  I'm sorry I don't have a better
answer for you, but the question you're asking now is much larger
than the original topic.
0
Reply txr1 (1241) 6/1/2012 12:34:30 AM

mike3 <mike4ty4@yahoo.com> writes:

> On May 29, 11:44 pm, mike3 <mike4...@yahoo.com> wrote:
> <snip>
>
> I've made an interesting and disturbing discovery.
>
> I found THIS:
>
> http://www.isc.org/software/bind/991
>
> I decided to have a look at the source code, and oh my goodness! What
> did I find?!
> Oh NO....!!!!!!!!!!!!!!!!!!!!!!! :
>
> ----
>
> idn_result_t
> idn_normalizer_add(idn_normalizer_t ctx, const char *scheme_name) {
> 	idn_result_t r;
> 	void *v;
> 	normalize_scheme_t *scheme;
>
> 	assert(ctx != NULL && scheme_name != NULL);
>
> 	TRACE(("idn_normalizer_add(scheme_name=%s)\n", scheme_name));
>
> 	assert(INITIALIZED);
>
> 	if (idn__strhash_get(scheme_hash, scheme_name, &v) != idn_success) {
> 		ERROR(("idn_normalizer_add(): invalid scheme \"%-.30s\"\n",
> 		       scheme_name));
> 		r = idn_invalid_name;
> 		goto ret;
> <----------------- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
> 	}
>
> 	scheme = v;
>
> 	assert(ctx->nschemes <= ctx->scheme_size);
>
> 	if (ctx->nschemes == ctx->scheme_size &&
> 	    (r = expand_schemes(ctx)) != idn_success) {
> 		goto ret;
> <----------------- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
> 	}
>
> 	ctx->schemes[ctx->nschemes++] = scheme;
> 	r = idn_success;
> ret:
> <----------------- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
> 	TRACE(("idn_normalizer_add(): %s\n", idn_result_tostring(r)));
> 	return (r);
> }
>
> ----
>
> YES, that's right -- those are GOTOs in there, and they do this a LOT
> in this program! Djikstra!!!

It's Dijkstra, OK?  Dijkstra.

The above is a terrible example.  It looks like programming by numbers:
"I've been told to trace entry and exit so I'll stick a label at the end
and replace returns with gotos".  I think it's clearer without them,
although there is some justification if my guess is right -- it might
have been a ploy to minimise re-writing.

> But as this thread seems to show, it looks like that there exist
> alternatives to GOTO, and so we can still uphold Djikstra's law.

It's not a law.  The famous article is a well-argued case.  Do read it
if you haven't.

> Or is there something about this program that makes it OK to use GOTOs
> in it, but it is not OK to use them in the one I'm doing?

I don't know the program, but this function does not benefit from having
gotos.  There are cases where a goto really helps, but they are far
fewer than some people think.

-- 
Ben.
0
Reply ben.usenet (6516) 6/1/2012 2:21:12 AM

On 06/ 1/12 11:46 AM, mike3 wrote:
> On May 29, 11:44 pm, mike3<mike4...@yahoo.com>  wrote:
> <snip>
>
> I've also noticed another problem. I've got a place where a
> routine needs to _return_ a BigNum it mints inside itself.
>
> ErrorCode MyFunc(BigNum **OutputValue)
> {
>            ...
>            *OutputValue = (BigNum *)malloc(sizeof(BigNum));
>            if(*OutputValue == NULL)
>              {
>                  <duplicated err handler>
>              }
>
>            rv = BigNum_Initialize(*OutputValue);
>            if(rv != ERROR_SUCCESS)
>              {
>                  <ditto>
>              }
>
>            ...
>            (error handlers in here that now have to _free the alloced
> memory
>            and not just deinit the BigNum_! What should I do about
> this?)
>            ...
> }
>
> What to do?

Use C++!

You appear to be using C++ already given your remarkably similar flame 
bait thread over on c.l.c++.

-- 
Ian Collins
0
Reply ian-news (9908) 6/1/2012 3:55:38 AM

mike3 wrote:
) So what would the "bad design" be in this case? There doesn't
) seem to be a whole lot of things that could be changed. A bignum
) system will have init, free, and arithmetic routines. Trouble
) seems to be due to the possibility of return codes on every
) bignum operation. Is this the "design problem"? Notice that
) something like, say, GMP, doesn't do that. All GMP functions
) return void or an arithmetic result, not an error code. But I *do*
) want to have some sort of error reporting functionality.

A better design would be to catch errors into the bignum type itself,
and propagate that through the calculations.  I.E.: Have 'error' be
a possible value for a bignum (or perhaps multiple 'error' values)
and whenever an 'error' value is used in a calculation, the result
is also (that same) 'error'.

That way, you can calculate away without error handling and at the
end do one single error check to see if everything went well.


SaSW, Willem
-- 
Disclaimer: I am in no way responsible for any of the statements
            made in the above text. For all I know I might be
            drugged or something..
            No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
0
Reply willem6 (255) 6/1/2012 7:40:37 AM

On May 31, 8:21 pm, Ben Bacarisse <ben.use...@bsb.me.uk> wrote:
> mike3 <mike4...@yahoo.com> writes:
> > YES, that's right -- those are GOTOs in there, and they do this a LOT
> > in this program! Djikstra!!!
>
> It's Dijkstra, OK?  Dijkstra.
>

OK...

> The above is a terrible example.  It looks like programming by numbers:
> "I've been told to trace entry and exit so I'll stick a label at the end
> and replace returns with gotos".  I think it's clearer without them,
> although there is some justification if my guess is right -- it might
> have been a ploy to minimise re-writing.
>

To me, it looks like they're trying to reuse the TRACE call. So that
one
could modify the TRACE call without having to modify a clone at
another
point in the routine. Would it be OK to duplicate the line at each
return
point?

> > But as this thread seems to show, it looks like that there exist
> > alternatives to GOTO, and so we can still uphold Djikstra's law.
>
> It's not a law.  The famous article is a well-argued case.  Do read it
> if you haven't.
>
> > Or is there something about this program that makes it OK to use GOTOs
> > in it, but it is not OK to use them in the one I'm doing?
>
> I don't know the program, but this function does not benefit from having
> gotos.  There are cases where a goto really helps, but they are far
> fewer than some people think.
>

Mmmm. So how would you write those returns?
0
Reply mike4ty4 (405) 6/1/2012 10:49:24 AM

On May 30, 12:26=A0pm, Willem <wil...@toad.stack.nl> wrote:
> tom st denis wrote:
>
> ) On May 30, 5:18?am, Willem <wil...@toad.stack.nl> wrote:
> )> If you want to be more concise, you can make ERROR_SUCCESS equal 0,
> )> and then you can simply do:
> )>
> )> ? ? rv =3D BigNum_Initialize(&a) || ... || BigNum_Set(&b, 3) || BigNum=
_AddTo(&a, &b) || ... ;
> )>
> )> Which will short-circuit at the first failure.
> )
> ) Which in a sufficiently complicated function like an ECC point add/
> ) double would result in spaghetti code and your termination. =A0:-)
>
> How can it be spaghetti when it's a single line of calls, one after
> the other? =A0Spaghetti code is meant to be tangled, isn't it?
>
> ) The "if (err =3D=3D OK) ..." method is cool but frankly I just like the
> ) goto's when I'm writing out something the long way.
>
> I've seen the (err =3D=3D OK) method used too much in code that didn't re=
quire
> cleanup at end of function. =A0Apparently somebody at our company believe=
s in
> 'one-function-one-return' religiously. =A0I agree gotos are better.
>
> Another method is to have all 'bignum' functions check for 'error' inputs
> and generate 'error' outputs when they encounter them (or whenever they
> =A0encounter an error), and then you only have to check for an 'error'
> result at the very end.
>
> Something like:
>
> int DoCalc()
> {
> =A0 int rv;
> =A0 BigNum a;
> =A0 BigNum b;
> =A0 BigNum c;
> =A0 BigNum d;
>
> =A0 BigNum_Init(&a);
> =A0 BigNum_Init(&b);
> =A0 BigNum_Init(&c);
> =A0 BigNum_Init(&d);
>
> =A0 BigNum_Set(&a, 3);
> =A0 BigNum_Set(&b, 5);
> =A0 ...
> =A0 BigNum_Multiply(&c, &d);
> =A0 ...
> =A0 if ((rv =3D BigNum_GetError(&d)) !=3D ERROR_SUCCESS) return rv;
>
> =A0 BigNum_Print("The result is: %bn", &d);
> =A0 BigNum_Free(&a);
> =A0 BigNum_Free(&b);
> =A0 BigNum_Free(&c);
> =A0 BigNum_Free(&d);
>
> =A0 return ERROR_SUCCESS;
>
> }
>
> The only weirdside to this is when a value is not used in the final resul=
t,
> then that value will not be checked for errors.

That only works if you capture the error codes in your bignum
structure otherwise it's not thread safe.

Tom
0
Reply tom236 (284) 6/1/2012 3:05:37 PM

Ben Bacarisse wrote:

>> But as this thread seems to show, it looks like that there exist
>> alternatives to GOTO, and so we can still uphold Djikstra's law.
> 
> It's not a law.  The famous article is a well-argued case.  Do read it
> if you haven't.

Knuth has a famous "retort" to the GOTO article.

Donald E. Knuth. 1974. Structured Programming with go to Statements. ACM 
Comput. Surv. 6, 4 (December 1974), 261-301. DOI=10.1145/356635.356640 
http://doi.acm.org/10.1145/356635.356640

-- 
Aaron W. Hsu | arcfide@sacrideo.us | http://www.sacrideo.us
Programming is just another word for the lost art of thinking.

0
Reply arcfide (659) 6/1/2012 4:06:37 PM

"Aaron W.  Hsu" <arcfide@sacrideo.us> writes:

> Ben Bacarisse wrote:
>
>>> But as this thread seems to show, it looks like that there exist
>>> alternatives to GOTO, and so we can still uphold Djikstra's law.
>> 
>> It's not a law.  The famous article is a well-argued case.  Do read it
>> if you haven't.
>
> Knuth has a famous "retort" to the GOTO article.

I am sure you know (hence the quotes) that it is not a refutation of
what Dijkstra wrote.  Knuth says:

  I argue for the elimination of go to's in certain cases, and for their
  introduction in others.  I believe that by presenting such a view I am
  not in fact disagreeing sharply with Dijkstra's ideas, since he
  recently wrote the following: "Please don't fall into the trap of
  believing that I am terribly dogmatical about [the go to statement]."

Both are models of clarity, and neither is dogmatic.  I feel sure that
if all gotos in all programs had been as well-reasoned for as those in
Knuth's paper, Dijkstra would never have written his.

> Donald E. Knuth. 1974. Structured Programming with go to Statements. ACM 
> Comput. Surv. 6, 4 (December 1974), 261-301. DOI=10.1145/356635.356640 
> http://doi.acm.org/10.1145/356635.356640

-- 
Ben.
0
Reply ben.usenet (6516) 6/2/2012 1:01:10 AM

mike3 <mike4ty4@yahoo.com> writes:

> On May 31, 8:21 pm, Ben Bacarisse <ben.use...@bsb.me.uk> wrote:
>> mike3 <mike4...@yahoo.com> writes:
>> > YES, that's right -- those are GOTOs in there, and they do this a LOT
>> > in this program! Djikstra!!!
<snip>
>> The above is a terrible example.  It looks like programming by numbers:
>> "I've been told to trace entry and exit so I'll stick a label at the end
>> and replace returns with gotos".  I think it's clearer without them,
>> although there is some justification if my guess is right -- it might
>> have been a ploy to minimise re-writing.
>
> To me, it looks like they're trying to reuse the TRACE call.

Yes, but what came first?  If the tracing was there originally and the
logic of the function was subsequently made more complex, doing it with
gotos makes no sense to me.  If the logic was there and used multiple
returns when the tracing was added, I can see some value in making the
minimum of changes -- just replace the returns with jumps.

> So that
> one could modify the TRACE call without having to modify a clone at
> another point in the routine. Would it be OK to duplicate the line at
> each return point?

No, of course not.

<snip>
>> I don't know the program, but this function does not benefit from having
>> gotos.  There are cases where a goto really helps, but they are far
>> fewer than some people think.
>
> Mmmm. So how would you write those returns?

Having got this far -- a single return -- I would add any more.  I'd
just write the function using natural structures rather than jumps:

  idn_result_t
  idn_normalizer_add(idn_normalizer_t ctx, const char *scheme_name) {
       idn_result_t r;
       void *v;
   
       assert(ctx != NULL && scheme_name != NULL);
       TRACE(("idn_normalizer_add(scheme_name=%s)\n", scheme_name));
       assert(INITIALIZED);
   
       if (idn__strhash_get(scheme_hash, scheme_name, &v) != idn_success) {
            ERROR(("idn_normalizer_add(): invalid scheme \"%-.30s\"\n",
                   scheme_name));
            r = idn_invalid_name;
       }
       else {
            assert(ctx->nschemes <= ctx->scheme_size);
   
            if (ctx->nschemes != ctx->scheme_size ||
                (r = expand_schemes(ctx)) == idn_success) {
                 ctx->schemes[ctx->nschemes++] = v;
                 r = idn_success;
            }
       }
       TRACE(("idn_normalizer_add(): %s\n", idn_result_tostring(r)));
       return r;
  }

(I've also removed an unneeded variable: "scheme", but it would probably
be better to rename "v" as "scheme" now.)

-- 
Ben.
0
Reply ben.usenet (6516) 6/2/2012 1:15:32 AM

On Jun 1, 7:15=A0pm, Ben Bacarisse <ben.use...@bsb.me.uk> wrote:
> mike3 <mike4...@yahoo.com> writes:
<snip>
> > To me, it looks like they're trying to reuse the TRACE call.
>
> Yes, but what came first? =A0If the tracing was there originally and the
> logic of the function was subsequently made more complex, doing it with
> gotos makes no sense to me. =A0If the logic was there and used multiple
> returns when the tracing was added, I can see some value in making the
> minimum of changes -- just replace the returns with jumps.
>

You mean a goto?

<snip>
> > Mmmm. So how would you write those returns?
>
> Having got this far -- a single return -- I would add any more. =A0I'd
> just write the function using natural structures rather than jumps:
>
> =A0 idn_result_t
> =A0 idn_normalizer_add(idn_normalizer_t ctx, const char *scheme_name) {
> =A0 =A0 =A0 =A0idn_result_t r;
> =A0 =A0 =A0 =A0void *v;
>
> =A0 =A0 =A0 =A0assert(ctx !=3D NULL && scheme_name !=3D NULL);
> =A0 =A0 =A0 =A0TRACE(("idn_normalizer_add(scheme_name=3D%s)\n", scheme_na=
me));
> =A0 =A0 =A0 =A0assert(INITIALIZED);
>
> =A0 =A0 =A0 =A0if (idn__strhash_get(scheme_hash, scheme_name, &v) !=3D id=
n_success) {
> =A0 =A0 =A0 =A0 =A0 =A0 ERROR(("idn_normalizer_add(): invalid scheme \"%-=
..30s\"\n",
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0scheme_name));
> =A0 =A0 =A0 =A0 =A0 =A0 r =3D idn_invalid_name;
> =A0 =A0 =A0 =A0}
> =A0 =A0 =A0 =A0else {
> =A0 =A0 =A0 =A0 =A0 =A0 assert(ctx->nschemes <=3D ctx->scheme_size);
>
> =A0 =A0 =A0 =A0 =A0 =A0 if (ctx->nschemes !=3D ctx->scheme_size ||
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 (r =3D expand_schemes(ctx)) =3D=3D idn_su=
ccess) {
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0ctx->schemes[ctx->nschemes++] =3D v;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0r =3D idn_success;
> =A0 =A0 =A0 =A0 =A0 =A0 }
> =A0 =A0 =A0 =A0}
> =A0 =A0 =A0 =A0TRACE(("idn_normalizer_add(): %s\n", idn_result_tostring(r=
)));
> =A0 =A0 =A0 =A0return r;
> =A0 }
>
> (I've also removed an unneeded variable: "scheme", but it would probably
> be better to rename "v" as "scheme" now.)
>

Hmm. This looks like the "nest" approach suggested on this thread by
Ike Naar. I suppose it'd be OK in this case, since there are only a
couple of
error-code-returning calls and so the nesting does not get too deep.
But
what if you had like 5 calls or more (and with something that's not a
bignum
package, so you couldn't, e.g. pass error codes inside bignums)?
0
Reply mike4ty4 (405) 6/2/2012 2:45:45 AM

On Jun 1, 7:01=A0pm, Ben Bacarisse <ben.use...@bsb.me.uk> wrote:
> "Aaron W. =A0Hsu" <arcf...@sacrideo.us> writes:
<snip>
> Both are models of clarity, and neither is dogmatic. =A0I feel sure that
> if all gotos in all programs had been as well-reasoned for as those in
> Knuth's paper, Dijkstra would never have written his.
>

But I take it that, from what I've seen on this thread, using gotos to
jump to error code handlers is _not_ a "well-reasoned" use, right, and
so
Djikstra's rules still apply?
0
Reply mike4ty4 (405) 6/2/2012 2:46:45 AM

On Jun 1, 8:46=A0pm, mike3 <mike4...@yahoo.com> wrote:
> On Jun 1, 7:01=A0pm, Ben Bacarisse <ben.use...@bsb.me.uk> wrote:
>
> > "Aaron W. =A0Hsu" <arcf...@sacrideo.us> writes:
> <snip>
> > Both are models of clarity, and neither is dogmatic. =A0I feel sure tha=
t
> > if all gotos in all programs had been as well-reasoned for as those in
> > Knuth's paper, Dijkstra would never have written his.
>
> But I take it that, from what I've seen on this thread, using gotos to
> jump to error code handlers is _not_ a "well-reasoned" use, right, and
> so
> Djikstra's rules still apply?
   ^^^^^^^^^
Damn, I did it again! Dijkstra, oops. :(
0
Reply mike4ty4 (405) 6/2/2012 4:19:41 AM

"mike3" <mike4ty4@yahoo.com> wrote in message
news:d4477aa8-f837-4bee-bb40-fbcc3da179c0@pr7g2000pbb.googlegroups.com...
> On May 29, 11:44 pm, mike3 <mike4...@yahoo.com> wrote:

> I've made an interesting and disturbing discovery.
>
> I found THIS:

> YES, that's right -- those are GOTOs in there, and they do this a LOT
> in this program!

I've just looked at the Python source code. I counted around 2000 gotos in 
200,000 lines of code. Mostly they seemed to be used in place of an early 
return, where there is common code to be executed before a return, so this 
is just written once at the end of a function.

It seems clear enough. Some people don't like goto because it can lead to
spaghetti code (eg. as used by io_x), but it doesn't need to.

> Djikstra!!!

I've no idea who you're talking about there...

-- 
Bartc 

0
Reply bc (2221) 6/2/2012 8:46:11 AM

On Sat, 02 Jun 2012 02:01:10 +0100, Ben Bacarisse wrote:

> Both are models of clarity, and neither is dogmatic.  I feel sure that
> if all gotos in all programs had been as well-reasoned for as those in
> Knuth's paper, Dijkstra would never have written his.

Indeed, that is why I tend to refer people to the Knuth response after 
reading Dijkstra's original.  Even today there is an unnecessary 
avoidance of GOTO, as if they are the root cause of all problems, when 
the problem both of the above authors really want to address is code that 
is not clear, reasoned, and justified. Spaghetti code should not exist, 
regardless of whether or not you use Gotos to write spaghetti code.

-- 
Aaron W. Hsu | arcfide@sacrideo.us | http://www.sacrideo.us
Programming is just another word for the lost art of thinking.
0
Reply arcfide (659) 6/2/2012 9:37:50 AM

On Jun 2, 3:37=A0am, "Aaron W. Hsu" <arcf...@sacrideo.us> wrote:
> On Sat, 02 Jun 2012 02:01:10 +0100, Ben Bacarisse wrote:
> > Both are models of clarity, and neither is dogmatic. =A0I feel sure tha=
t
> > if all gotos in all programs had been as well-reasoned for as those in
> > Knuth's paper, Dijkstra would never have written his.
>
> Indeed, that is why I tend to refer people to the Knuth response after
> reading Dijkstra's original. =A0Even today there is an unnecessary
> avoidance of GOTO, as if they are the root cause of all problems, when
> the problem both of the above authors really want to address is code that
> is not clear, reasoned, and justified. Spaghetti code should not exist,
> regardless of whether or not you use Gotos to write spaghetti code.
>

So does using GOTOs to jump to error handlers make the code less
clear, reasoned, and justified (see the example in my OP)? How do they
affect the clarity of the "real world program" code snippet I posted?
0
Reply mike4ty4 (405) 6/2/2012 10:40:16 AM

On 5/30/2012 8:13 AM, ImpalerCore wrote:

> On a side note, the term ERROR_SUCCESS appears contradictory to me.  I
> would prefer something like NO_ERROR or SUCCESS if you had control
> over the error definitions.

I agree.  With an ERROR prefix I would use ERROR_NONE.  My preference, though, 
is to use <module>_SUCCESS (or <module>_OK), where <module> is replaced by a 
name that designates the particular module whose status is being reported.

Thad

0
Reply ThadSmith (1279) 6/2/2012 1:20:45 PM

mike3 <mike4ty4@yahoo.com> writes:

> On Jun 2, 3:37 am, "Aaron W. Hsu" <arcf...@sacrideo.us> wrote:
>> On Sat, 02 Jun 2012 02:01:10 +0100, Ben Bacarisse wrote:
>> > Both are models of clarity, and neither is dogmatic.  I feel sure that
>> > if all gotos in all programs had been as well-reasoned for as those in
>> > Knuth's paper, Dijkstra would never have written his.

It's been a while since I read it, so I read it again and I am no longer
so sure.

The surprising thing is that the note (it less then two pages long) is
about go to in programming languages -- not in programs.  In effect, it
is a call to language designers to provide the right set of control
structures so that go to's are no longer needed.

Of course, the problem he so clearly identifies -- the fact that
unbridled use of the go to (note: _unbridled use_) leads to code that
can't be understood without maintaining a very complex view of the
code's execution sate -- applies to code written in those languages that
already have a go to statement.

>> Indeed, that is why I tend to refer people to the Knuth response after
>> reading Dijkstra's original.  Even today there is an unnecessary
>> avoidance of GOTO, as if they are the root cause of all problems, when
>> the problem both of the above authors really want to address is code that
>> is not clear, reasoned, and justified. Spaghetti code should not exist,
>> regardless of whether or not you use Gotos to write spaghetti code.
>
> So does using GOTOs to jump to error handlers make the code less
> clear, reasoned, and justified (see the example in my OP)? How do they
> affect the clarity of the "real world program" code snippet I posted?

To my mind, yes.  However, the code is short and simple to re-write
without goto, so it is neither a good example of what Dijkstra was
arguing against, nor is it a good example of what Knuth was arguing to
retain.  Because it is short, it is not particularly hard to reason
about (though it is harder to reason about than the goto-free version)
and because the pattern is simple to re-write without goto, it not a
case that shows the value of retaining goto in the language.

-- 
Ben.
0
Reply ben.usenet (6516) 6/2/2012 1:46:13 PM

mike3 <mike4ty4@yahoo.com> writes:

> On Jun 1, 7:01 pm, Ben Bacarisse <ben.use...@bsb.me.uk> wrote:
>> "Aaron W.  Hsu" <arcf...@sacrideo.us> writes:
> <snip>
>> Both are models of clarity, and neither is dogmatic.  I feel sure that
>> if all gotos in all programs had been as well-reasoned for as those in
>> Knuth's paper, Dijkstra would never have written his.
>
> But I take it that, from what I've seen on this thread, using gotos to
> jump to error code handlers is _not_ a "well-reasoned" use, right,

A well-reasoned use needs reasoning.  Your recent example did not
include any reasoning, just a slightly facetious remark that you'd found
a goto in real code (multiple exclamation marks!!!).

In certain cases, depending on the logic, the case for a jump to a block
of common clean-up code can be made.  It needs care to get it right
since you are often cleaning up an incomplete configuration using
variables whose cope is, by definition, nearly all of (and in C90 is all
of) the function body.

Your example was a bad one because the jump-free version is, to my mind,
clearer and simpler.

> and so Djikstra's rules still apply?

(You've corrected the name error.)

Go read the note -- it less then two pages.  Honestly, go read it.  It
does not present a rule for programmers, so much as a call for language
designers to provide control structures that are easy to reason about.
If gotos are still needed, it suggests a lack of suitable alternatives.

-- 
Ben.
0
Reply ben.usenet (6516) 6/2/2012 1:50:55 PM

In article <slrnjscii7.2aju.willem@toad.stack.nl>,
Willem  <willem@toad.stack.nl> wrote:
>I agree gotos are better.

I agree gotos are better.

int func(int x)
{
    int err;
    struct bar *a;
    struct bar *b;
    struct bar *c;
    int err2;

    err = allocate_bar(&a);
    if (err != X_OK)
	goto done;

    err = allocate_bar(&b);
    if (err != X_OK)
	goto free_a;

    err = allocate_bar(&c);
    if (err != X_OK)
	goto free_b;

    ...

    /* normal exit */

    err = free_bar(c);

    err2 = free_bar(b);
    err = err != X_OK ? err : err2;

    err2 = free_bar(a);
    err = err != X_OK ? err : err2;
    return err;

    /* error exit */

    err2 = free_bar(c);
    (void) err2;

  free_b:
    err2 = free_bar(b);
    (void) err2;

  free_a:
    err2 = free_bar(a);
    (void) err2;

  done:
    return err;
}

do that in C++!
0
Reply jgk1 (176) 6/2/2012 1:54:24 PM

mike3 <mike4ty4@yahoo.com> writes:

> On Jun 1, 7:15 pm, Ben Bacarisse <ben.use...@bsb.me.uk> wrote:
>> mike3 <mike4...@yahoo.com> writes:
> <snip>
>> > To me, it looks like they're trying to reuse the TRACE call.
>>
>> Yes, but what came first?  If the tracing was there originally and the
>> logic of the function was subsequently made more complex, doing it with
>> gotos makes no sense to me.  If the logic was there and used multiple
>> returns when the tracing was added, I can see some value in making the
>> minimum of changes -- just replace the returns with jumps.
>
> You mean a goto?

Yes.

> <snip>
>> > Mmmm. So how would you write those returns?
>>
>> Having got this far -- a single return -- I would add any more.  I'd
>> just write the function using natural structures rather than jumps:
>>
>>   idn_result_t
>>   idn_normalizer_add(idn_normalizer_t ctx, const char *scheme_name) {
>>        idn_result_t r;
>>        void *v;
>>
>>        assert(ctx != NULL && scheme_name != NULL);
>>        TRACE(("idn_normalizer_add(scheme_name=%s)\n", scheme_name));
>>        assert(INITIALIZED);
>>
>>        if (idn__strhash_get(scheme_hash, scheme_name, &v) != idn_success) {
>>             ERROR(("idn_normalizer_add(): invalid scheme \"%-.30s\"\n",
>>                    scheme_name));
>>             r = idn_invalid_name;
>>        }
>>        else {
>>             assert(ctx->nschemes <= ctx->scheme_size);
>>
>>             if (ctx->nschemes != ctx->scheme_size ||
>>                 (r = expand_schemes(ctx)) == idn_success) {
>>                  ctx->schemes[ctx->nschemes++] = v;
>>                  r = idn_success;
>>             }
>>        }
>>        TRACE(("idn_normalizer_add(): %s\n", idn_result_tostring(r)));
>>        return r;
>>   }
>>
>> (I've also removed an unneeded variable: "scheme", but it would probably
>> be better to rename "v" as "scheme" now.)
>>
>
> Hmm. This looks like the "nest" approach suggested on this thread by
> Ike Naar. I suppose it'd be OK in this case, since there are only a
> couple of error-code-returning calls and so the nesting does not get
> too deep.  But what if you had like 5 calls or more (and with
> something that's not a bignum package, so you couldn't, e.g. pass
> error codes inside bignums)?

Give an example, and I'll comment.  I can't see exactly what it is you
are saying.  I presume it is not just the code that you originally
posted, since I commented on that.

Having, multiple early error cases does not always lead to conceptually
deep nesting.  If you have:

  if (C1) {
    rc = E1;
    goto error;
  }
  if (C2) {
    rc = E2;
    goto error;
  }
  if (C3) {
    rc = E3;
    goto error;
  }
  /* main error-free code */
 error:
  /* common clean-up code */
  return rc;

you can turn it into:

  if (C1)
    rc = E1;
  else if (C2)
    rc = E2;
  else if (C3)
    rc = E3;
  else {
    /* main error-free code */
  }
  /* common clean-up code */
  return rc;

That's deeply nested in the most literal sense, but no one would have
any trouble reasoning about the nesting, eleven if were 100 levels deep.

-- 
Ben.
0
Reply ben.usenet (6516) 6/2/2012 2:00:52 PM

=D7=91=D7=AA=D7=90=D7=A8=D7=99=D7=9A =D7=99=D7=95=D7=9D =D7=A9=D7=91=D7=AA,=
 2 =D7=91=D7=99=D7=95=D7=A0=D7=99 2012 03:46:45 UTC+1, =D7=9E=D7=90=D7=AA m=
ike3:
>
> But I take it that, from what I've seen on this thread, using gotos to
> jump to error code handlers is _not_ a "well-reasoned" use, right, and
> so Djikstra's rules still apply?
>
Gotos for error handling ia a well reasoned use. Being able to give cogent =
reasons for doing something doesn't mean that it is right, or that someone =
else might be able to give even better reasons against. But it's rather dif=
ferent from the situation where an action is taken without consideration, o=
r in ignorance of the problems that may be associated with it.
0
Reply malcolm.mclean5 (750) 6/2/2012 2:04:33 PM

On Jun 2, 3:54 pm, j...@panix.com (Joe keane) wrote:

> I agree gotos are better.

#define SIZE 3
int func(int x)
{
int i, err;
struct bar *s[SIZE];

// init
 for( err=X_OK, i=0; (err==X_OK) && (i<SIZE); i++ )
  err = allocate_bar( &s[i] );

// check success
 if( err == X_OK )
 { // process ...
 }

// free only allocated bar(s)
 while( --i >= 0 ) free_bar( s[i] );

// done
return err; // zero = success
}


> int func(int x)
> {
>     int err;
>     struct bar *a;
>     struct bar *b;
>     struct bar *c;
>     int err2;
>
>     err = allocate_bar(&a);
>     if (err != X_OK)
>         goto done;
>
>     err = allocate_bar(&b);
>     if (err != X_OK)
>         goto free_a;
>
>     err = allocate_bar(&c);
>     if (err != X_OK)
>         goto free_b;
>
>     ...
>
>     /* normal exit */
>
>     err = free_bar(c);
>
>     err2 = free_bar(b);
>     err = err != X_OK ? err : err2;
>
>     err2 = free_bar(a);
>     err = err != X_OK ? err : err2;
>     return err;
>
>     /* error exit */
>
>     err2 = free_bar(c);
>     (void) err2;
>
>   free_b:
>     err2 = free_bar(b);
>     (void) err2;
>
>   free_a:
>     err2 = free_bar(a);
>     (void) err2;
>
>   done:
>     return err;
> }
0
Reply 5.d (68) 6/2/2012 2:24:44 PM

jgk@panix.com (Joe keane) writes:

> In article <slrnjscii7.2aju.willem@toad.stack.nl>,
> Willem  <willem@toad.stack.nl> wrote:
>>I agree gotos are better.
>
> I agree gotos are better.
>
> int func(int x)
> {
>     int err;
>     struct bar *a;
>     struct bar *b;
>     struct bar *c;
>     int err2;
>
>     err = allocate_bar(&a);
>     if (err != X_OK)
> 	goto done;
>
>     err = allocate_bar(&b);
>     if (err != X_OK)
> 	goto free_a;
>
>     err = allocate_bar(&c);
>     if (err != X_OK)
> 	goto free_b;
>
>     ...
>
>     /* normal exit */
>
>     err = free_bar(c);
>
>     err2 = free_bar(b);
>     err = err != X_OK ? err : err2;
>
>     err2 = free_bar(a);
>     err = err != X_OK ? err : err2;
>     return err;
>
>     /* error exit */
>
>     err2 = free_bar(c);
>     (void) err2;

This code is unreachable but I think it's not needed by any path so it's
probably just there due to an editing error.

>   free_b:
>     err2 = free_bar(b);
>     (void) err2;
>
>   free_a:
>     err2 = free_bar(a);
>     (void) err2;
>
>   done:
>     return err;
> }
>
> do that in C++!

Why do you think this is not already C++?

BTW, to my mind this API is broken.  I like allocation functions that
return NULL on failure.  If you need more data, an error-collecting
parameter can be passed.  Having NULL pointers make it possible to write
clean-up code that does not depend on the order of allocation.

However, using the same API, I'd write:

  int func(int x)
  {
      int err_a, err_b, err_c;
      struct bar *a, *b, *c;
 
      err_a = allocate_bar(&a);
      err_b = allocate_bar(&b);
      err_c = allocate_bar(&c);

      if (err_a == X_OK && err_b == X_OK && err_c == X_OK) {
         /* normal code */
      }
 
      if (err_a == X_OK) err_a = free_bar(a);
      if (err_b == X_OK) err_b = free_bar(b);
      if (err_c == X_OK) err_c = free_bar(c);
 
      return err_a == X_OK && err_b == X_OK && err_c == X_OK;
  }

This does not return the same value, as your code but that's not hard to
change.  I found your code's preference for one possible error over
another to be a little odd, so I changed it to appear more uniform.

-- 
Ben.
0
Reply ben.usenet (6516) 6/2/2012 2:42:27 PM

"io_x" <a@b.c.invalid> ha scritto nel messaggio
news:4fc61d23$0$1385$4fafbaef@reader2.news.tin.it...
>
> "mike3" <mike4ty4@yahoo.com> ha scritto nel messaggio
> news:7e54cf3c-d514-407b-a9b6-c0009589d242@ra8g2000pbc.googlegroups.com...
>> Hi.
>>
>> I've got some stuff that looks like this:
>
> this is my way...

this could be my way...
probabily i use not well C macro...
'2' exit[it is always one]: one for error one for ok

#include <stdio.h>

#define  u32   unsigned
#define  u64   unsigned __int64
#define  i32   int
#define  u16   unsigned short
#define  u8    unsigned char
#define  i8    char
#define  i16   short
#define  long_long   __int64

#define  sdC  __stdcall
#define  ooo  cout
#define  S    sizeof
#define  MM   Malloc_m
#define  FF   Free_m
#define  F   for
#define  R   return
#define  W   while
#define  G   goto
#define  P   printf
#define  jj(x) if((x)==-1)  goto

typedef u32*  BigNum;

// dummy functions
i32  BigNum_Initialize(BigNum*  a)          {R (i32)(*a=0);}
i32  BigNum_Set(BigNum* a, u32  b)          {R (i32)(*a=(u32*)b);}
i32  BigNum_Add(BigNum* c,BigNum*  b, u32 r){R (i32)(*c=(u32*)((u32)*b+r));}
i32  BigNum_Add(BigNum* c,BigNum*  b, BigNum* r)
{R (i32)(*c=(u32*)((u32)*b+(u32)*r));}
i32  BigNum_Free(BigNum* a)                 {R (i32)(*a=0);}

i32 MyFunc(void)
{BigNum   a, b, c, d;

 P("Inizio a=%u b=%u c=%u d=%u\n", a, b, c, d);
 if(BigNum_Initialize(&a)== -1)
    {ex0: R  -1;}
 if(BigNum_Initialize(&b)== -1)
    {ex1:   BigNum_Free(&a); G  ex0;}
 if(BigNum_Initialize(&c)== -1)
    {ex2:   BigNum_Free(&b); G  ex1;}
 if(BigNum_Initialize(&d)== -1)
    {ex3:   BigNum_Free(&c); G  ex2;}

 P("Inizilizzati a=%u b=%u c=%u d=%u\n", a, b, c, d);

 if(BigNum_Set(&b, 3)==-1)
    {ex4:   BigNum_Free(&d); G  ex3;}

 jj(BigNum_Add(&c, &b, 3)) ex4;
 jj(BigNum_Add(&a, &d, 3)) ex4;
 jj(BigNum_Add(&d, &c,&a)) ex4;
// etc
// ....
          /* free buffers */
 P("fine a=%u b=%u c=%u d=%u\n", a, b, c, d);

 jj(BigNum_Free(&d))  ex3;
 jj(BigNum_Free(&c))  ex2;
 jj(BigNum_Free(&b))  ex1;
 jj(BigNum_Free(&a))  ex0;

 P("fine1 a=%u b=%u c=%u d=%u\n", a, b, c, d);
 R   0;
}

main(void){R MyFunc();}



0
Reply io_x 6/2/2012 3:34:39 PM

"Ben Bacarisse" <ben.usenet@bsb.me.uk> wrote in message
> To my mind, yes.  However, the code is short and simple to re-write
> without goto, so it is neither a good example of what Dijkstra was
> arguing against, nor is it a good example of what Knuth was arguing to
> retain.  Because it is short, it is not particularly hard to reason
> about (though it is harder to reason about than the goto-free version)
> and because the pattern is simple to re-write without goto, it not a
> case that shows the value of retaining goto in the language.

The fact that C is quite often used a compilation target for other
languages, is enough reason to retain the goto statement. (Even forgetting
the millions of lines of existing code.)

Any control statement that doesn't exactly match one of C's limited
selection of statements, can easily be translated instead into a series of
conditional statements and gotos. Then there might be housekeeping code,
common return code, etc that doesn't fit into a structured programming
pattern, as well as actual spaghetti code, using gotos, in the source
language.

(Actually, you can probably get rid of most control statements; just leave a 
simple if-statement (you don't need else), and goto. These are the most 
important.)

While there might be theoretical ways of always being able to eliminate all
gotos by convoluting the code and adding extra state variables, it's far
easier just to use gotos. Especially in target code that no-one is ever
going to read.

But for actually writing in C, obviously you will use them sparingly.

-- 
Bartc 

0
Reply bc (2221) 6/2/2012 4:10:51 PM

In article <fc325350-fecd-4c33-a0f7-29c3faad1208@tx6g2000pbc.googlegroups.com>,
mike3  <mike4ty4@yahoo.com> wrote:
> On Jun 1, 8:46 pm, mike3 <mike4...@yahoo.com> wrote:

[ snip ]

> > Djikstra's rules still apply?
>    ^^^^^^^^^
> Damn, I did it again! Dijkstra, oops. :(

Maybe you will find the following useful as a way of remembering
(I *think* I got this from a native speaker of Dutch, though I may
be misremembering):  "Dykstra" might be a more logical spelling,
and the "i" and "j" together look sort of like a "y".  FWIW?

-- 
B. L. Massingill
ObDisclaimer:  I don't speak for my employers; they return the favor.
0
Reply blmblm (1187) 6/2/2012 4:35:09 PM

In article <a77db563-a307-4c82-a32d-18fbc238afec@cu1g2000vbb.googlegroups.com>,
Jean-Christophe  <5.d@free.fr> wrote:
>#define SIZE 3
>int func(int x)
>{
>int i, err;
>struct bar *s[SIZE];
>
>// init
> for( err=X_OK, i=0; (err==X_OK) && (i<SIZE); i++ )
>  err = allocate_bar( &s[i] );
>
>// check success
> if( err == X_OK )
> { // process ...
> }
>
>// free only allocated bar(s)
> while( --i >= 0 ) free_bar( s[i] );
>
>// done
>return err; // zero = success
>}

I used 'struct bar',
for all of them,
for sake of example.

It's very likely that in real world code
they are all different types,
with different functions to allocate them and unallocate them,
and so some code to iterate over them is likely to be
some more confusing than helpful.

If they are the same type,
such that you can put them in an array,
then of course what you say is better.
0
Reply jgk1 (176) 6/2/2012 4:37:43 PM

Joe keane wrote:

> In article <slrnjscii7.2aju.willem@toad.stack.nl>,
> Willem  <willem@toad.stack.nl> wrote:
>>I agree gotos are better.
>
> I agree gotos are better.
>
> int func(int x)
> {
>     int err;
>     struct bar *a;
>     struct bar *b;
>     struct bar *c;
>     int err2;
>
>     err = allocate_bar(&a);
>     if (err != X_OK)
> 	goto done;
>
>     err = allocate_bar(&b);
>     if (err != X_OK)
> 	goto free_a;
>
>     err = allocate_bar(&c);
>     if (err != X_OK)
> 	goto free_b;
>
>     ...
>
>     /* normal exit */
>
>     err = free_bar(c);
>
>     err2 = free_bar(b);
>     err = err != X_OK ? err : err2;
>
>     err2 = free_bar(a);
>     err = err != X_OK ? err : err2;
>     return err;
>
>     /* error exit */
>
>     err2 = free_bar(c);
>     (void) err2;
>
>   free_b:
>     err2 = free_bar(b);
>     (void) err2;
>
>   free_a:
>     err2 = free_bar(a);
>     (void) err2;
>
>   done:
>     return err;
> }
>
> do that in C++!

If you insist. :)

void func(int x)
{
	std::unique_ptr<bar> a = new bar();
	std::unique_ptr<bar> b = new bar();
	std::unique_ptr<bar> c = new bar();

	...
}

Martin Shobe

0
Reply martin.shobe (19) 6/2/2012 7:27:55 PM

In article <0.ad98122c5f4b9fe6aef5.20120602154227BST.87aa0lepws.fsf@bsb.me.uk>,
Ben Bacarisse  <ben.usenet@bsb.me.uk> wrote:
>I like allocation functions that return NULL on failure.

I like allocation functions that set the carry bit on failure.

My own convention is that if a function returns less than zero, it has
reset your state to the most extent possible, and none of the 'output'
parameters are changed (but be liberal in what you receive).

IMHE the stupid mistakes occur when you mix together conventions [it
-should- be easy to do this, but we are just monkeys].

When you prevent stupid mistakes, you force people to make the more
complicated mistakes.
0
Reply jgk1 (176) 6/2/2012 7:35:59 PM

On 2 juin, 18:37, j...@panix.com (Joe keane) :

> I used 'struct bar',
> for all of them, for sake of example.
> It's very likely that in real world code
> they are all different types,
> with different functions to allocate them and unallocate them,
> and so some code to iterate over them is likely to be
> some more confusing than helpful.

I'd rather encapsulate functions pointers
( allocate, init, ... etc ... )
into the structure itself, to allow the
use of identical syntax all down the code.
It makes it more readable, and shorter.
And still, this is not C++, juste pure C.
0
Reply 5.d (68) 6/2/2012 7:46:35 PM

On Jun 2, 8:00 am, Ben Bacarisse <ben.use...@bsb.me.uk> wrote:
> mike3 <mike4...@yahoo.com> writes:
<snip>
> > You mean a goto?
>
> Yes.
>

Thanks for the explanation.

<snip>
> > Hmm. This looks like the "nest" approach suggested on this thread by
> > Ike Naar. I suppose it'd be OK in this case, since there are only a
> > couple of error-code-returning calls and so the nesting does not get
> > too deep.  But what if you had like 5 calls or more (and with
> > something that's not a bignum package, so you couldn't, e.g. pass
> > error codes inside bignums)?
>
> Give an example, and I'll comment.  I can't see exactly what it is you
> are saying.  I presume it is not just the code that you originally
> posted, since I commented on that.
>
> Having, multiple early error cases does not always lead to conceptually
> deep nesting.  If you have:
>
>   if (C1) {
>     rc = E1;
>     goto error;
>   }
>   if (C2) {
>     rc = E2;
>     goto error;
>   }
>   if (C3) {
>     rc = E3;
>     goto error;
>   }
>   /* main error-free code */
>  error:
>   /* common clean-up code */
>   return rc;
>
> you can turn it into:
>
>   if (C1)
>     rc = E1;
>   else if (C2)
>     rc = E2;
>   else if (C3)
>     rc = E3;
>   else {
>     /* main error-free code */
>   }
>   /* common clean-up code */
>   return rc;
>
> That's deeply nested in the most literal sense, but no one would have
> any trouble reasoning about the nesting, eleven if were 100 levels deep.
>

So you're suggesting to abuse the if() to create a list of executed
functions
that breaks off at an error, then, right? Is that a "dirty" trick?

0
Reply mike4ty4 (405) 6/2/2012 11:44:39 PM

mike3 <mike4ty4@yahoo.com> writes:

> On Jun 2, 8:00 am, Ben Bacarisse <ben.use...@bsb.me.uk> wrote:
>> mike3 <mike4...@yahoo.com> writes:
> <snip>
>> > You mean a goto?
>>
>> Yes.
>>
>
> Thanks for the explanation.
>
> <snip>
>> > Hmm. This looks like the "nest" approach suggested on this thread by
>> > Ike Naar. I suppose it'd be OK in this case, since there are only a
>> > couple of error-code-returning calls and so the nesting does not get
>> > too deep.  But what if you had like 5 calls or more (and with
>> > something that's not a bignum package, so you couldn't, e.g. pass
>> > error codes inside bignums)?
>>
>> Give an example, and I'll comment.  I can't see exactly what it is you
>> are saying.  I presume it is not just the code that you originally
>> posted, since I commented on that.
>>
>> Having, multiple early error cases does not always lead to conceptually
>> deep nesting.  If you have:
>>
>>   if (C1) {
>>     rc = E1;
>>     goto error;
>>   }
>>   if (C2) {
>>     rc = E2;
>>     goto error;
>>   }
>>   if (C3) {
>>     rc = E3;
>>     goto error;
>>   }
>>   /* main error-free code */
>>  error:
>>   /* common clean-up code */
>>   return rc;
>>
>> you can turn it into:
>>
>>   if (C1)
>>     rc = E1;
>>   else if (C2)
>>     rc = E2;
>>   else if (C3)
>>     rc = E3;
>>   else {
>>     /* main error-free code */
>>   }
>>   /* common clean-up code */
>>   return rc;
>>
>> That's deeply nested in the most literal sense, but no one would have
>> any trouble reasoning about the nesting, eleven if were 100 levels deep.
>
> So you're suggesting to abuse the if() to create a list of executed
> functions
> that breaks off at an error, then, right? Is that a "dirty" trick?

I can't made head or tail of that.  If you consider my use of if .. else
if ... to be an abuse, I doubt we have enough common ground debate this
point, but that seems like an unlikely position to hold and does not
explain the "list of executed functions" remark.

-- 
Ben.
0
Reply ben.usenet (6516) 6/3/2012 2:51:29 AM

jgk@panix.com (Joe keane) writes:

> In article <0.ad98122c5f4b9fe6aef5.20120602154227BST.87aa0lepws.fsf@bsb.me.uk>,
> Ben Bacarisse  <ben.usenet@bsb.me.uk> wrote:
>>I like allocation functions that return NULL on failure.
>
> I like allocation functions that set the carry bit on failure.

I wish you and the carry bit all the best.

<snip>
-- 
Ben.
0
Reply ben.usenet (6516) 6/3/2012 2:53:03 AM

"io_x" <a@b.c.invalid> ha scritto nel messaggio
news:4fca3222$0$1380$4fafbaef@reader2.news.tin.it...
> #include <stdio.h>
>
> #define  u32   unsigned
> #define  u64   unsigned __int64
> #define  i32   int
> #define  u16   unsigned short
> #define  u8    unsigned char
> #define  i8    char
> #define  i16   short
> #define  long_long   __int64
>
> #define  sdC  __stdcall
> #define  ooo  cout
> #define  S    sizeof
> #define  MM   Malloc_m
> #define  FF   Free_m
> #define  F   for
> #define  R   return
> #define  W   while
> #define  G   goto
> #define  P   printf
> #define  jj(x) if((x)==-1)  goto
>
> typedef u32*  BigNum;
>
> // dummy functions
> i32  BigNum_Initialize(BigNum*  a)          {R (i32)(*a=0);}
> i32  BigNum_Set(BigNum* a, u32  b)          {R (i32)(*a=(u32*)b);}
> i32  BigNum_Add(BigNum* c,BigNum*  b, u32 r){R (i32)(*c=(u32*)((u32)*b+r));}
> i32  BigNum_Add(BigNum* c,BigNum*  b, BigNum* r)
> {R (i32)(*c=(u32*)((u32)*b+(u32)*r));}
> i32  BigNum_Free(BigNum* a)                 {R (i32)(*a=0);}
>
> i32 MyFunc(void)
> {BigNum   a, b, c, d;
>
> P("Inizio a=%u b=%u c=%u d=%u\n", a, b, c, d);
> if(BigNum_Initialize(&a)== -1)
>    {ex0: R  -1;}
> if(BigNum_Initialize(&b)== -1)
>    {ex1:   BigNum_Free(&a); G  ex0;}
> if(BigNum_Initialize(&c)== -1)
>    {ex2:   BigNum_Free(&b); G  ex1;}
> if(BigNum_Initialize(&d)== -1)
>    {ex3:   BigNum_Free(&c); G  ex2;}
>
> P("Inizilizzati a=%u b=%u c=%u d=%u\n", a, b, c, d);
>
> if(BigNum_Set(&b, 3)==-1)
>    {ex4:   BigNum_Free(&d); G  ex3;}
>
> jj(BigNum_Add(&c, &b, 3)) ex4;
> jj(BigNum_Add(&a, &d, 3)) ex4;
> jj(BigNum_Add(&d, &c,&a)) ex4;
> // etc
> // ....
>          /* free buffers */
> P("fine a=%u b=%u c=%u d=%u\n", a, b, c, d);
>
> jj(BigNum_Free(&d))  ex3;
> jj(BigNum_Free(&c))  ex2;
> jj(BigNum_Free(&b))  ex1;
> jj(BigNum_Free(&a))  ex0;
>
> P("fine1 a=%u b=%u c=%u d=%u\n", a, b, c, d);
> R   0;
> }
>
> main(void){R MyFunc();}

at end i wuold write something as:
i32 MyFunc(BigNum*  x)
{BigNum   a, b, c, d;
 if(x==0)       R  -1;
 a=0; b=3; c=b+3; *x=c+a+d;
 if(x->err())   R  -1;
 else           R   0;
}

but would be the OT c++...
yes it is intendend all c++ exceptions turn off
but except the one
"write out of mem reserved to that program"





0
Reply io_x 6/3/2012 8:33:17 AM

"BartC" <bc@freeuk.com> ha scritto nel messaggio
news:jqcjta$7mk$1@dont-email.me...
> "mike3" <mike4ty4@yahoo.com> wrote in message
> news:d4477aa8-f837-4bee-bb40-fbcc3da179c0@pr7g2000pbb.googlegroups.com...
>> On May 29, 11:44 pm, mike3 <mike4...@yahoo.com> wrote:
>
>> I've made an interesting and disturbing discovery.
>>
>> I found THIS:
>
>> YES, that's right -- those are GOTOs in there, and they do this a LOT
>> in this program!
>
> I've just looked at the Python source code. I counted around 2000 gotos in
> 200,000 lines of code. Mostly they seemed to be used in place of an early
> return, where there is common code to be executed before a return, so this is
> just written once at the end of a function.
>
> It seems clear enough. Some people don't like goto because it can lead to
> spaghetti code (eg. as used by io_x), but it doesn't need to.

so you know what structured programming mean?

>> Djikstra!!!

so Djikstra know what structured programming mean?
"structured programming" has something in common to write
down in code the correct algo?

if someone speak not good for goto he/she make wrong...
he she don't know to what he she is talking about...

it is good find a way to write easy one algo
and find a way for find easily errors in that too
but it need art

> I've no idea who you're talking about there...
>
> -- 
> Bartc





0
Reply io_x 6/3/2012 8:43:11 AM


"io_x" <a@b.c.invalid> wrote in message
news:4fcb2258$0$1375$4fafbaef@reader2.news.tin.it...
>
> "BartC" <bc@freeuk.com> ha scritto nel messaggio

>> It seems clear enough. Some people don't like goto because it can lead to
>> spaghetti code (eg. as used by io_x), but it doesn't need to.
>
> so you know what structured programming mean?

Something like this I guess:

http://en.wikipedia.org/wiki/Structured_programming

> so Djikstra know what structured programming mean?
> "structured programming" has something in common to write
> down in code the correct algo?
>
> if someone speak not good for goto he/she make wrong...
> he she don't know to what he she is talking about...

It's not just black and white. You wouldn't use 'goto' to replace the
if-else, while, do-while, switch and for statements, because the code would
be much more obscure. But I can't see the problem in using it where no
suitable control statement exists (although others would argue that it is
better then to turn the code upside-down so that it does fit into the
statements that are available).

(I couldn't find a copy of Dijkstra's letter; there's an annotated version
here, with his text in blue: http://david.tribble.com/text/goto.html)

> it is good find a way to write easy one algo
> and find a way for find easily errors in that too
> but it need art

It needs that you are the one who wrote the original code, and that you are 
reading the same code five minutes later.

-- 
Bartc 

0
Reply bc (2221) 6/3/2012 9:58:49 AM

tom st denis wrote:
) On May 30, 12:26?pm, Willem <wil...@toad.stack.nl> wrote:
)> Another method is to have all 'bignum' functions check for 'error' inputs
)> and generate 'error' outputs when they encounter them (or whenever they
)> ?encounter an error), and then you only have to check for an 'error'
)> result at the very end.
)>
)> Something like:

<snip>

)> The only weirdside to this is when a value is not used in the final result,
)> then that value will not be checked for errors.
)
) That only works if you capture the error codes in your bignum
) structure otherwise it's not thread safe.

I don't see any way to implement what I described other than storing
the error codes in the bignum structures.


SaSW, Willem
-- 
Disclaimer: I am in no way responsible for any of the statements
            made in the above text. For all I know I might be
            drugged or something..
            No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
0
Reply willem6 (255) 6/3/2012 11:24:26 AM

"BartC" <bc@freeuk.com> writes:
>be much more obscure. But I can't see the problem in using it where no
>suitable control statement exists (although others would argue that it is

  One of the problems is code alteration: When you have a
  large section of code including jump statements, it might be
  difficult to extract a part of it into a method (jumps might
  go into and out of this section, which will not work anymore
  after extraction) or to do other forms of code alteration.

  When each block has exactly one entrance at its beginning
  and exactly one exit at its end, I call it a �structured
  block�.

  The code alteration of the first paragraph seems to be
  easier with structured blocks. It also might be easier to
  read and to argue about properties of that code segment or
  to prove them; the mere wording �precondition�,
  �postcondition�, and �invariant� of a block seem to imply
  that it is a structured block.

0
Reply ram (2839) 6/3/2012 3:11:22 PM

"BartC" <bc@freeuk.com> ha scritto nel messaggio
news:jqfcgt$i8m$1@dont-email.me...
>> it is good find a way to write easy one algo
>> and find a way for find easily errors in that too
>> but it need art
>
> It needs that you are the one who wrote the original code, and that you are
> reading the same code five minutes later.

i read my code only in case of bug...i think i could not read code from some
other one...

i don't know for debug-understand other code, but for my code i not have
problem;
can be years  1000 yesars etc etc...
yes i not use much comment, for find one error i use the debug for find
the 10-20 lines that generate the error; without understand the remain...

than i debug these line for to see what dey do
and what they do when error came out...
and for this, there is some time because one has to understand all:
why this, why that, etc
until the error is found; until now, using above method
i found all error i searched.
these bugs came out one time 30-90 days or when i change the library
functions etc

for example the last one...
some day ago i test if the new library goes well with the old program...
but there was one error;
i just track down all function changed from old-new dll
but no step toward find the error...

so i trace for find the function find for the first the error:
it was one time function, the error is not in the new function
but in the old ones in a time function that found "this day"
the last day of the month, is not right... and so return error

the error was that in time library the tables for days in month
are wrong

daytab   db   0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
daytabL  db   0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31

instead of
;              1   2   3   4   5   6   7   8   9  10  11  12
daytab   db   31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
daytabL  db   31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31

and the function return error because it
find that the now day is not right
i change the table and all ok...
this error could no came out easily because came out only in
the last day of the month if the month is the one right :)
i think i like track down errors it is like read one book
of Agatha Cristie...



0
Reply io_x 6/3/2012 3:18:40 PM

"io_x" <a@b.c.invalid> ha scritto nel messaggio 
news:4fcb2258$0$1375$4fafbaef@reader2.news.tin.it...
>
> "BartC" <bc@freeuk.com> ha scritto nel messaggio
> news:jqcjta$7mk$1@dont-email.me...
>> "mike3" <mike4ty4@yahoo.com> wrote in message
>> news:d4477aa8-f837-4bee-bb40-fbcc3da179c0@pr7g2000pbb.googlegroups.com...
>>> On May 29, 11:44 pm, mike3 <mike4...@yahoo.com> wrote:
>>> Djikstra!!!
>
> so Djikstra know what structured programming mean?

error above: "Dijkstra" excuse me... 


0
Reply io_x 6/3/2012 3:30:42 PM

On 3 juin, 17:30, "io_x" <a...@b.c.invalid> wrote:

> Dijkstra know what structured programming mean?

Edsgar Dijkstra is a quiche eater:
http://powerdown.free.fr/rp.html
0
Reply 5.d (68) 6/3/2012 4:02:02 PM

Jean-Christophe <5.d@free.fr> writes:

> On 3 juin, 17:30, "io_x" <a...@b.c.invalid> wrote:
>
>> Dijkstra know what structured programming mean?
>
> Edsgar Dijkstra is a quiche eater:
> http://powerdown.free.fr/rp.html

"Was", not "is".  He died in 2002.

To get a flavour of what a real "quiche eater" is like, read his
development of a program to find the convex hull of a set of 3D points,
which is done in parallel with the development of a proof of the
algorithm's correctness.[1]  In fact, read the whole book, if you have
time.  It changed the way I think about programming.

[1] E. W. Dijkstra, "A Discipline of Programming", Prentice Hall, 1977,
Chapter 24, pp 168--191.

-- 
Ben.
0
Reply ben.usenet (6516) 6/3/2012 9:37:33 PM

In article <jqdpfq$pqs$1@dont-email.me>,
Martin Shobe  <martin.shobe@yahoo.com> wrote:
>If you insist. :)
>
>void func(int x)
>{
>	std::unique_ptr<bar> a = new bar();
>	std::unique_ptr<bar> b = new bar();
>	std::unique_ptr<bar> c = new bar();
>
>	...
>}

Does it return the correct error code if an error occurs in the
unallocate function?
0
Reply jgk1 (176) 6/3/2012 11:48:18 PM

On 06/ 4/12 11:48 AM, Joe keane wrote:
> In article<jqdpfq$pqs$1@dont-email.me>,
> Martin Shobe<martin.shobe@yahoo.com>  wrote:
>> If you insist. :)
>>
>> void func(int x)
>> {
>> 	std::unique_ptr<bar>  a = new bar();
>> 	std::unique_ptr<bar>  b = new bar();
>> 	std::unique_ptr<bar>  c = new bar();
>>
>> 	...
>> }
>
> Does it return the correct error code if an error occurs in the
> unallocate function?

delete does not return errors and func is declared void.

Your code ignored the errors from free_bar (in a very ugly fashion I 
might add).

-- 
Ian Collins
0
Reply ian-news (9908) 6/3/2012 11:53:59 PM

Joe keane wrote:

> In article <jqdpfq$pqs$1@dont-email.me>,
> Martin Shobe  <martin.shobe@yahoo.com> wrote:
>>If you insist. :)
>>
>>void func(int x)
>>{
>>	std::unique_ptr<bar> a = new bar();
>>	std::unique_ptr<bar> b = new bar();
>>	std::unique_ptr<bar> c = new bar();
>>
>>	...
>>}
>
> Does it return the correct error code if an error occurs in the
> unallocate function?

Return it? No. But it would throw the correct exception.

Martin Shobe

0
Reply martin.shobe (19) 6/4/2012 3:32:11 AM

On 2012-06-03, Ben Bacarisse <ben.usenet@bsb.me.uk> wrote:
> Jean-Christophe <5.d@free.fr> writes:
>> Edsgar Dijkstra is a quiche eater:
>> http://powerdown.free.fr/rp.html
>
> "Was", not "is".  He died in 2002.
>
> To get a flavour of what a real "quiche eater" is like, read his
> development of a program to find the convex hull of a set of 3D points,
> which is done in parallel with the development of a proof of the
> algorithm's correctness.[1]  In fact, read the whole book, if you have
> time.  It changed the way I think about programming.
>
> [1] E. W. Dijkstra, "A Discipline of Programming", Prentice Hall, 1977,
> Chapter 24, pp 168--191.

Another book, that describes the same ideas in a more accessible manner,
is David Gries' "The Science of Programming", Springer, 1981.
With a foreword by E.W. Dijkstra.
0
Reply ike7 (162) 6/4/2012 7:28:39 AM

In article <goto-20120603170542@ram.dialup.fu-berlin.de>,
Stefan Ram <ram@zedat.fu-berlin.de> wrote:
>  The code alteration of the first paragraph seems to be
>  easier with structured blocks. It also might be easier to
>  read and to argue about properties of that code segment or
>  to prove them; the mere wording �precondition�,
>  �postcondition�, and �invariant� of a block seem to imply
>  that it is a structured block.

What i see here is that the postcondition typically comprises two
conditions, one for normal exit, one for error exit, and they are
usually pretty dissimilar.  So i'm not sure that insisting on one
postcondition really buys you any simplicity.

In terms of code, it's always nice to see the normal exit first, then
the error handling.  Someone who just wants to get some idea how a
function works does not need to plow through the latter.  Of course we
want to be sure that it's right, but it's often just distracting.
0
Reply jgk1 (176) 6/4/2012 8:40:40 PM

jgk@panix.com (Joe keane) writes:
>What i see here is that the postcondition typically comprises two
>conditions

  It is not mentioned on

http://en.wikipedia.org/wiki/Postcondition

  and I am not aware of any source speaking of such /two/
  postconditions.

0
Reply ram (2839) 6/4/2012 10:30:33 PM

In article <postconditions-20120605002952@ram.dialup.fu-berlin.de>,
Stefan Ram <ram@zedat.fu-berlin.de> wrote:
>  It is not mentioned on
>
>http://en.wikipedia.org/wiki/Postcondition

?

'a postcondition is a condition or predicate that must always be true
just after the execution of some section of code'

e.g.

    int foo(int x)
    {
	int y;

	if (x == 0)
	{
	    y = 0;
	}
	else
	{
	    y = 1;
	}

	return y;    
    }

A precondition of the first block is "x == 0".
A precondition of the second block is "x != 0".
A postcondition of the first block is "x == 0 && y == 0".
A postcondition of the second block is "x != 0 && y != 0".

A postcondition of the if/else construct is
"x == 0 && y == 0 || x != 0 && y != 0".
0
Reply jgk1 (176) 6/5/2012 1:03:40 AM

jgk@panix.com (Joe keane) writes:
>A precondition of the first block is "x == 0".
 
  This is the /second/ compound statement. The /first/
  compound statement starts at the first brace in your code.
 
>A postcondition of the first block is "x == 0 && y == 0".

  This is /one/ postcondition. Before, you wrote:

>>>the postcondition typically comprises two conditions 
                                         ���
  . There is no source that says so (except your post).

0
Reply ram (2839) 6/5/2012 1:19:08 AM

In article <postconditions-20120605002952@ram.dialup.fu-berlin.de>,
Stefan Ram <ram@zedat.fu-berlin.de> wrote:
>  and I am not aware of any source speaking of such /two/
>  postconditions.

http://en.wikipedia.org/wiki/Hoare_triple#Conditional_rule

any language with an if/else construct has two postconditions

    {B && P} S {Q}, {!B && P} T {Q}
    ----
    {P} if B then S else T endif {Q}

or mine

    {B && P} S {Q}, {!B && P} T {R}
    ----
    {P} if B then S else T endif {Q || R}

identical since "Q" -> "Q || R", "R" -> "Q || R", "Q || Q" -> "Q" are
tautologies
0
Reply jgk1 (176) 6/5/2012 2:05:40 AM

jgk@panix.com (Joe keane) writes:
>any language with an if/else construct has two postconditions

  A language does not have postconditions,
  a statement has a postcondition.

  The webpage you mentioned does not support
  your claims.

0
Reply ram (2839) 6/5/2012 2:28:13 AM

Joe keane wrote:

> In article <postconditions-20120605002952@ram.dialup.fu-berlin.de>,
> Stefan Ram <ram@zedat.fu-berlin.de> wrote:
>>  and I am not aware of any source speaking of such /two/
>>  postconditions.
>
> http://en.wikipedia.org/wiki/Hoare_triple#Conditional_rule
>
> any language with an if/else construct has two postconditions
>
>     {B && P} S {Q}, {!B && P} T {Q}
>     ----
>     {P} if B then S else T endif {Q}

Only one postcondition here (namely Q).

>
> or mine
>
>     {B && P} S {Q}, {!B && P} T {R}
>     ----
>     {P} if B then S else T endif {Q || R}
>
> identical since "Q" -> "Q || R", "R" -> "Q || R", "Q || Q" -> "Q" are
> tautologies

Again, only one post condition here (namely Q || R).

And before you try to say that Q is one postcondition and R is the
other, consider that, in general, neither Q nor R are postconditions by
themselves.

Martin Shobe


Martin Shobe

0
Reply martin.shobe (19) 6/5/2012 3:16:58 AM

ram@zedat.fu-berlin.de (Stefan Ram) writes:

> jgk@panix.com (Joe keane) writes:
>>A precondition of the first block is "x == 0".
>  
>   This is the /second/ compound statement. The /first/
>   compound statement starts at the first brace in your code.
>  
>>A postcondition of the first block is "x == 0 && y == 0".
>
>   This is /one/ postcondition. Before, you wrote:
>
>>>>the postcondition typically comprises two conditions 
>                                          ¯¯¯
>   . There is no source that says so (except your post).

I think he's talking about what he's seen in his experience, not a
definition -- that he's tended to see postconditions of the form
(a || b) where 'a' means "the postcondition you'd expect from a naive
statement of the algorithm" and 'b' means "some strange kludge that came
about as a result of an error in the course of executing the code".
0
Reply pfeiffer (618) 6/5/2012 3:36:39 AM

In article <jq4nar$lvm$1@dont-email.me>,
MarkBluemel  <mark_bluemel@pobox.com> wrote:
>On 05/30/2012 06:44 AM, mike3 wrote:
>
>ErrorCode MyFunc()
>{
>           BigNum a = BIGNUM_NULL;
>           BigNum b = BIGNUM_NULL;
>           BigNum c = BIGNUM_NULL;
>           BigNum d = BIGNUM_NULL;
>           ErrorCode rv;
>
>           rv = BigNum_Initialize(&a);
>           if(rv != ERROR_SUCCESS)
>            goto failed;
>
>           ...
>
>failed: /* we'll try and clean up, but won't care too much if it fails */
>         if (d != BIGNUM_NULL)
>           BigNum_Free(&d);
>         ...

This is the style I tend to prefer. I've written a lot of device drivers
in the past, and the attach function generally has to catch about a
dozen failure cases. This is pretty much the cleanest & safest way
to deal with it.

-- 
	-Ed Falk, falk@despams.r.us.com
	http://thespamdiaries.blogspot.com/
0
Reply falk3260 (91) 6/5/2012 7:20:52 AM

On 2012-06-05, Stefan Ram <ram@zedat.fu-berlin.de> wrote:
> jgk@panix.com (Joe keane) writes:
>>A precondition of the first block is "x == 0".
>  
>   The /first/
>   compound statement starts at the first brace in your code.

A real quiche-eater would call that the zero-th compound statement ;-)
0
Reply ike8 (164) 6/5/2012 8:12:58 AM

On 06/05/2012 04:12 AM, Ike Naar wrote:
> On 2012-06-05, Stefan Ram <ram@zedat.fu-berlin.de> wrote:
>> jgk@panix.com (Joe keane) writes:
>>> A precondition of the first block is "x == 0".
>>  
>>   The /first/
>>   compound statement starts at the first brace in your code.
> 
> A real quiche-eater would call that the zero-th compound statement ;-)

Such people really do exist; I once had a very confusing discussion with
someone who insisted on misusing English that way.
-- 
James Kuyper
0
Reply jameskuyper (5207) 6/5/2012 10:00:19 AM

James Kuyper <jameskuyper@verizon.net> writes:
>On 06/05/2012 04:12 AM, Ike Naar wrote:
>>On 2012-06-05, Stefan Ram <ram@zedat.fu-berlin.de> wrote:
>>>jgk@panix.com (Joe keane) writes:
>>>>A precondition of the first block is "x == 0".
>>>The /first/
>>>compound statement starts at the first brace in your code.
>>A real quiche-eater would call that the zero-th compound statement ;-)
>Such people really do exist; I once had a very confusing discussion with
>someone who insisted on misusing English that way.

  See also

http://www.purl.org/stefan_ram/pub/zero

  .

0
Reply ram (2839) 6/5/2012 10:50:53 AM

In article <1bzk8ibfaw.fsf@pfeifferfamily.net>,
Joe Pfeiffer  <pfeiffer@cs.nmsu.edu> wrote:
>I think he's talking about what he's seen in his experience, not a
>definition

I think i'm talking about what i've seen in my experience, not a
definition

>-- that he's tended to see postconditions of the form (a || b)

i tended to see all postconditions of the form

    IF [error code is zero] THEN
	all operations we did completed successfuly
	go ahead with what you wanted to do
    ELSE /* error code is not zero */
	at least one thing we tried did not complete successfully
	we tried to clean it up but we can not guarantee that
	we tried to return the error code for the -first- error
	if you fix the first error we can probably do a better job
	at telling you what if anything else is wrong
    ENDIF

>where 'a' means "the postcondition you'd expect from a naive statement
>of the algorithm" and 'b' means "some strange kludge that came about as
>a result of an error in the course of executing the code".

; handling 'double errors' you will never get -right-, but at least you can
try to be helpful.
0
Reply jgk1 (176) 6/5/2012 3:13:40 PM

On May 31, 5:39 pm, mike3 <mike4...@yahoo.com> wrote:
> On May 29, 11:44 pm, mike3 <mike4...@yahoo.com> wrote:
<snip>

I've been wondering about this. _Why_ was a GOTO used in this
program? How could one be used in _such a high-profile program
like that_? And it's not just a lone GOTO or a few here and there,
as I said, this program is infected with a serious case of GOTOitis...
0
Reply mike4ty4 (405) 6/6/2012 9:54:56 AM

mike3 <mike4ty4@yahoo.com> writes:

> On May 31, 5:39 pm, mike3 <mike4...@yahoo.com> wrote:
>> On May 29, 11:44 pm, mike3 <mike4...@yahoo.com> wrote:
> <snip>
>
> I've been wondering about this. _Why_ was a GOTO used in this
> program? How could one be used in _such a high-profile program
> like that_? And it's not just a lone GOTO or a few here and there,
> as I said, this program is infected with a serious case of GOTOitis...

You'd have to ask the people who wrote it.

Some of the code looks extraordinary to me.  Whilst the vast majority of
goto's are clearly of the "error cleanup" sort, they are not all like
that.  For example there is this pattern:

        cmsgp = CMSG_FIRSTHDR(msg);
        while (cmsgp != NULL) {
                socket_log(...);

#ifdef ISC_PLATFORM_HAVEIN6PKTINFO
                if (...) {
                        /* stuff */
                        goto next;
                }
#endif

#ifdef SO_TIMESTAMP
                if (...) {
                        /* stuff */
                        goto next;
                }
#endif
        next:
                cmsgp = CMSG_NXTHDR(msg, cmsgp);
        }

Why is this not just a for loop?  Failing that, why not just remove the
label and the goto's?  Maybe this is a fossilised relic of some much
more complex code.

Although there may well be a reason the code ended up like this, I hope
everyone agrees that it would be odd (to say the least) to write it like
this from scratch.

-- 
Ben.
0
Reply ben.usenet (6516) 6/6/2012 12:14:43 PM

On 2012-06-06, mike3 <mike4ty4@yahoo.com> wrote:
> On May 31, 5:39 pm, mike3 <mike4...@yahoo.com> wrote:
>> On May 29, 11:44 pm, mike3 <mike4...@yahoo.com> wrote:
><snip>
>
> I've been wondering about this. _Why_ was a GOTO used in this
> program? How could one be used in _such a high-profile program
> like that_? And it's not just a lone GOTO or a few here and there,
> as I said, this program is infected with a serious case of GOTOitis...

A quick search through the source code of Linux 3.2.12 reveals no less
than 94422 goto statements.

I agree that one should think very carefully about using a goto statement
where structured code would be much better. But there are, especially in
exception handling (which, um, C doesn't really provide), cases where the
use of a goto statement produces much more elegant code.

There is an interesting read about it all here:
http://kerneltrap.org/node/553/2131


I agree with what Scott Robert Ladd states: Bad code is produced by bad
programmers, not by bad language features.


-- 
"C provides a programmer with more than enough rope to hang himself.
C++ provides a firing squad, blindfold and last cigarette."
- seen in comp.lang.c
0
Reply news104 (781) 6/6/2012 1:06:28 PM

Ben Bacarisse wrote:
> 
> mike3 <mike4ty4@yahoo.com> writes:
> 
> > On May 31, 5:39 pm, mike3 <mike4...@yahoo.com> wrote:
> >> On May 29, 11:44 pm, mike3 <mike4...@yahoo.com> wrote:
> > <snip>
> >
> > I've been wondering about this. _Why_ was a GOTO used in this
> > program? How could one be used in _such a high-profile program
> > like that_? And it's not just a lone GOTO or a few here and there,
> > as I said, this program is infected with a serious case of GOTOitis...
> 
> You'd have to ask the people who wrote it.
> 
> Some of the code looks extraordinary to me.  Whilst the vast majority of
> goto's are clearly of the "error cleanup" sort, they are not all like
> that.  For example there is this pattern:
> 
>         cmsgp = CMSG_FIRSTHDR(msg);
>         while (cmsgp != NULL) {
>                 socket_log(...);
> 
> #ifdef ISC_PLATFORM_HAVEIN6PKTINFO
>                 if (...) {
>                         /* stuff */
>                         goto next;
>                 }
> #endif
> 
> #ifdef SO_TIMESTAMP
>                 if (...) {
>                         /* stuff */
>                         goto next;
>                 }
> #endif
>         next:
>                 cmsgp = CMSG_NXTHDR(msg, cmsgp);
>         }
> 
> Why is this not just a for loop?
> Failing that, why not just remove the
> label and the goto's?  Maybe this is a fossilised relic of some much
> more complex code.
> 
> Although there may well be a reason
> the code ended up like this, I hope
> everyone agrees that it would be odd (to say the least)
> to write it like this from scratch.

It may be the case 
that it is, or was, somewhat common 
for expert proffesional programmers
to have accomplished a lot of proffesional programming work
before they became experts.

I recall many many years ago, 
showing some crappy looking code to my new boss,
and him telling me that because of time constraints
I would soon be writing crappy looking code too.
And he was right.
They hired me when they needed a programmer right away,
and I didn't know C or good writing style
nearly as well as I do now,
and because of time constraints, I had to program quickly.

-- 
pete
0
Reply pfiland (6614) 6/6/2012 1:22:18 PM

pete wrote:
) I recall many many years ago, 
) showing some crappy looking code to my new boss,
) and him telling me that because of time constraints
) I would soon be writing crappy looking code too.
) And he was right.
) They hired me when they needed a programmer right away,
) and I didn't know C or good writing style
) nearly as well as I do now,
) and because of time constraints, I had to program quickly.

Your boss obviously was unaware that crappy code saves time in the
short run, but costs more time (with compound interest) in the long run.

But it seems that choosing short term benefits over long term benefits
is all the rage these days, so that is no surprise.


SaSW, Willem
-- 
Disclaimer: I am in no way responsible for any of the statements
            made in the above text. For all I know I might be
            drugged or something..
            No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
0
Reply willem6 (255) 6/6/2012 1:49:56 PM

Willem wrote:

> Your boss obviously was unaware that crappy code saves time in the
> short run, but costs more time (with compound interest) in the long run.
> 
> But it seems that choosing short term benefits over long term benefits
> is all the rage these days, so that is no surprise.

If someone is in the business of fixing problems, writing crappy code saves 
time in the short run and guarantees a bit of a cash flow in the long run.

http://dilbert.com/strips/comic/1995-11-13/


Rui Maciel
0
Reply rui.maciel (1761) 6/6/2012 1:56:42 PM

On 06/06/2012 09:49 AM, Willem wrote:
....
> But it seems that choosing short term benefits over long term benefits
> is all the rage these days, so that is no surprise.

"these days"? Has it ever not been so?
0
Reply jameskuyper (5207) 6/6/2012 2:17:57 PM


ErrorCode MyFunc()
{
=A0 BigNum a, b, c, d;
=A0 ErrorCode rv =3D ERROR_SUCCESS;

  BigNum * const vars[] =3D {&a,&b,&c,&d};
  int inits;

  // Try to initialise our variables
  for(inits =3D 0; inits < 4 && rv =3D=3D ERROR_SUCCESS; ++inits){
      rv =3D BigNum_Initialize(vars[inits]);
  }

  // On success, do maths
  if(rv =3D=3D ERROR_SUCCESS) {
    // Do some maths
  }

  // Unwind the stack of successful initialisations
  for(; inits > 0; --inits){
    BigNum_Free(vars[inits-1]);
 }
 return rv;
}
0
Reply gwowen (532) 6/6/2012 3:12:43 PM

On Jun 6, 7:06=A0am, Angel <angel+n...@spamcop.net> wrote:
> On 2012-06-06, mike3 <mike4...@yahoo.com> wrote:
>
> > On May 31, 5:39 pm, mike3 <mike4...@yahoo.com> wrote:
> >> On May 29, 11:44 pm, mike3 <mike4...@yahoo.com> wrote:
> ><snip>
>
> > I've been wondering about this. _Why_ was a GOTO used in this
> > program? How could one be used in _such a high-profile program
> > like that_? And it's not just a lone GOTO or a few here and there,
> > as I said, this program is infected with a serious case of GOTOitis...
>
> A quick search through the source code of Linux 3.2.12 reveals no less
> than 94422 goto statements.
>
> I agree that one should think very carefully about using a goto statement
> where structured code would be much better. But there are, especially in
> exception handling (which, um, C doesn't really provide), cases where the
> use of a goto statement produces much more elegant code.
>
> There is an interesting read about it all here:http://kerneltrap.org/node=
/553/2131
>
> I agree with what Scott Robert Ladd states: Bad code is produced by bad
> programmers, not by bad language features.
>

So would you say that using GOTO in the program I originally asked
about to
handle the errors would be an "acceptable use"?
0
Reply mike4ty4 (405) 6/7/2012 11:26:04 PM

Ben Bacarisse <ben.usenet@bsb.me.uk> writes:

> Jean-Christophe <5.d@free.fr> writes:
>
>> On 3 juin, 17:30, "io_x" <a...@b.c.invalid> wrote:
>>
>>> Dijkstra know what structured programming mean?
>>
>> Edsgar Dijkstra is a quiche eater:
>> http://powerdown.free.fr/rp.html
>
> "Was", not "is".  He died in 2002.
>
> To get a flavour of what a real "quiche eater" is like, read his
> development of a program to find the convex hull of a set of 3D points,
> which is done in parallel with the development of a proof of the
> algorithm's correctness.[1]  In fact, read the whole book, if you have
> time.  It changed the way I think about programming.
>
> [1] E. W. Dijkstra, "A Discipline of Programming", Prentice Hall, 1977,
> Chapter 24, pp 168--191.

An excellent book!  A little difficult to read on
one's own, I think.  I was lucky enough to get it
almost direct from the horse's mouth, in a course
taught by Martin Rem (who had been one of Dijkstra's
doctoral students).  I count this as one of my three
main influences in program development.
0
Reply txr1 (1241) 6/8/2012 8:28:28 AM

On 2012-06-07, mike3 <mike4ty4@yahoo.com> wrote:
> On Jun 6, 7:06?am, Angel <angel+n...@spamcop.net> wrote:
>> On 2012-06-06, mike3 <mike4...@yahoo.com> wrote:
>>
>> > On May 31, 5:39 pm, mike3 <mike4...@yahoo.com> wrote:
>> >> On May 29, 11:44 pm, mike3 <mike4...@yahoo.com> wrote:
>> ><snip>
>>
>> > I've been wondering about this. _Why_ was a GOTO used in this
>> > program? How could one be used in _such a high-profile program
>> > like that_? And it's not just a lone GOTO or a few here and there,
>> > as I said, this program is infected with a serious case of GOTOitis...
>>
>> A quick search through the source code of Linux 3.2.12 reveals no less
>> than 94422 goto statements.
>>
>> I agree that one should think very carefully about using a goto statement
>> where structured code would be much better. But there are, especially in
>> exception handling (which, um, C doesn't really provide), cases where the
>> use of a goto statement produces much more elegant code.
>>
>> There is an interesting read about it all here:
>> http://kerneltrap.org/node/553/2131
>>
>> I agree with what Scott Robert Ladd states: Bad code is produced by bad
>> programmers, not by bad language features.
>
> So would you say that using GOTO in the program I originally asked
> about to
> handle the errors would be an "acceptable use"?

Since I haven't looked at the original program you refer to, I cannot
say really. My only point here is that not all uses of goto are
automatically "evil", and that there are real-life situations where its
use is justified and leads to better code.


-- 
"C provides a programmer with more than enough rope to hang himself.
C++ provides a firing squad, blindfold and last cigarette."
- seen in comp.lang.c
0
Reply news104 (781) 6/8/2012 2:26:30 PM

On Jun 8, 8:26=A0am, Angel <angel+n...@spamcop.net> wrote:
> On 2012-06-07, mike3 <mike4...@yahoo.com> wrote:
<snip>
> > So would you say that using GOTO in the program I originally asked
> > about to
> > handle the errors would be an "acceptable use"?
>
> Since I haven't looked at the original program you refer to, I cannot
> say really. My only point here is that not all uses of goto are
> automatically "evil", and that there are real-life situations where its
> use is justified and leads to better code.
>

I was referring to the example I showed in my OP:

http://groups.google.com/group/comp.lang.c/msg/338e8ac90f710e5e?hl=3Den&dmo=
de=3Dsource
0
Reply mike4ty4 (405) 6/8/2012 10:19:02 PM

On 2012-06-08, mike3 <mike4ty4@yahoo.com> wrote:
> On Jun 8, 8:26?am, Angel <angel+n...@spamcop.net> wrote:
>> On 2012-06-07, mike3 <mike4...@yahoo.com> wrote:
><snip>
>> > So would you say that using GOTO in the program I originally asked
>> > about to
>> > handle the errors would be an "acceptable use"?
>>
>> Since I haven't looked at the original program you refer to, I cannot
>> say really. My only point here is that not all uses of goto are
>> automatically "evil", and that there are real-life situations where its
>> use is justified and leads to better code.
>>
>
> I was referring to the example I showed in my OP:
>
> http://groups.google.com/group/comp.lang.c/msg/338e8ac90f710e5e?hl=en&
> dmode=source

Perhaps it's not for me to say, as I haven't programmed seriously in
years. But I think this is exactly the same argument that the Linux
kernel people made for their use of "goto". So no, I personally don't
think the use of "goto" is bad in your example.

C has many features that make those who love structured code cry. But
IMHO, it's not the language's duty to protect bad programmers from
themselves. It's a tool, and it's  up to the programmer how that tool
gets used.


-- 
"C provides a programmer with more than enough rope to hang himself.
C++ provides a firing squad, blindfold and last cigarette."
- seen in comp.lang.c
0
Reply news104 (781) 6/8/2012 11:32:20 PM


"mike3" <mike4ty4@yahoo.com> wrote in message 
news:69250d7c-11b6-4fad-9594-224298f17b2d@t1g2000pbl.googlegroups.com...
> On Jun 8, 8:26 am, Angel <angel+n...@spamcop.net> wrote:
>> On 2012-06-07, mike3 <mike4...@yahoo.com> wrote:
> <snip>
>> > So would you say that using GOTO in the program I originally asked
>> > about to
>> > handle the errors would be an "acceptable use"?
>>
>> Since I haven't looked at the original program you refer to, I cannot
>> say really. My only point here is that not all uses of goto are
>> automatically "evil", and that there are real-life situations where its
>> use is justified and leads to better code.
>>
>
> I was referring to the example I showed in my OP:
>
> http://groups.google.com/group/comp.lang.c/msg/338e8ac90f710e5e?hl=en&dmode=source

If you take the function with the gotos, and simplify the structure, it 
looks like this:

    Init(a); if(x) goto f0;
    Init(b); if(x) goto f1;
    Init(c); if(x) goto f2;
    Init(d); if(x) goto f3;

    Set(b,3);  if(x) goto f4;

    Free(d); if(x) goto f3;
    Free(c); if(x) goto f2;
    Free(b); if(x) goto f1;
    Free(a); if(x) goto f0;
    return(p);

f4: Free(d);
f3: Free(c);
f2: Free(b);
f1: Free(a);
f0:
    return(q);

'x' is an error condition. In this form, you can see it is completely 
dominated by gotos. And not in a simple pattern either. In fact, I would say 
this qualifies as spaghetti code, even though all the gotos jump forward. 
This could almost be some 1970s Basic code!

And there's something not quite right about this code. But apart from 
anything else, there is a lot of repetition here: many lines almost 
identical to each other. Perhaps some sort of loop is called for.

Also notice that the first block of Free() is error-checked; the second 
block isn't; why not? Free(d) fails, you then Free(c), but don't seem to 
care if that is OK or not. In that case, why bother checking the first lot? 
Again, the two blocks do almost the same thing. (Imagine 26 variables 
instead of 4, then it's clear this approach doesn't scale well.)

Even in this abbreviated form, with only four variables, and a single-line 
main body, it's difficult to see what needs freeing, and what doesn't. This 
has been discussed before: it's easier to arrange things so that you can 
free an object unconditionally.

Or perhaps make use of variable-argument functions (I've never used them 
myself), then you can have:

rv=MultiInit(a,b,c,d,...)   /* stops at first error */

rv=MultiFree(a,b,c,d,....); /* returns first error, but frees the rest */

-- 
Bartc 

0
Reply bc (2221) 6/9/2012 12:14:43 AM

On 9 juin, 02:14, "BartC" :

> (...) Or perhaps make use of variable-argument functions
> (I've never used them myself), then you can have:
> rv=MultiInit(a,b,c,d,...)   /* stops at first error */
> rv=MultiFree(a,b,c,d,....); /* returns first error, but frees the rest */

Still, if there are a lot of parameters (aa,ab,ac,...,zz)
then wouldn't it be better to init/free by using a loop ?
Assuming that a,b,c are different types of data structures,
it would make sense to use some struct to implement a void* pointer
to the data structures and pointers to their init/free functions,
initializing data w/ their pointers in a loop and stop at first error,
free data in a loop : don't need any goto, makes code shorter and more
clear.
0
Reply 5.d (68) 6/9/2012 11:36:58 AM

=D7=91=D7=AA=D7=90=D7=A8=D7=99=D7=9A =D7=99=D7=95=D7=9D =D7=A9=D7=91=D7=AA,=
 9 =D7=91=D7=99=D7=95=D7=A0=D7=99 2012 01:14:43 UTC+1, =D7=9E=D7=90=D7=AA B=
art:
>=20
> If you take the function with the gotos, and simplify the structure, it=
=20
> looks like this:
>=20
>     Init(a); if(x) goto f0;
>     Init(b); if(x) goto f1;
>     Init(c); if(x) goto f2;
>     Init(d); if(x) goto f3;
>=20
>     Set(b,3);  if(x) goto f4;
>=20
>     Free(d); if(x) goto f3;
>     Free(c); if(x) goto f2;
>     Free(b); if(x) goto f1;
>     Free(a); if(x) goto f0;
>     return(p);
>=20
> f4: Free(d);
> f3: Free(c);
> f2: Free(b);
> f1: Free(a);
> f0:
>     return(q);
>=20
> 'x' is an error condition. In this form, you can see it is completely=20
> dominated by gotos. And not in a simple pattern either. In fact, I would =
say=20
> this qualifies as spaghetti code,=20
>
The central mistake is that the the consturctor takes an empty structure to=
 fill in, rather than returning a pointer to an allocated structure. Then t=
he destructor itself can return an error.
Change this, and you get

     Init(a); if(x) goto f0;
     Init(b); if(x) goto f0;
     Init(c); if(x) goto f0;
     Init(d); if(x) goto f0;
=20
     Set(b,3);  if(x) goto f0;
=20
     Free(d);=20
     Free(c);=20
     Free(b);=20
     Free(a);
     return(p);
=20
 f0: Free(d);
     Free(c);
     Free(b);
     Free(a);
     return(q);

That's much mpre acceptable. The control flow is still doiminated by gotos,=
 but that's because all the calls can return errors, which go into a single=
 error handler.

 
0
Reply malcolm.mclean5 (750) 6/9/2012 12:54:21 PM

"Malcolm McLean" <malcolm.mclean5@btinternet.com> wrote in message 
news:538a3102-833f-4a0b-a790-733cc91629fa@googlegroups.com...
> בתאריך יום שבת, 9 ביוני 2012 01:14:43 UTC+1, מאת Bart:
>>
>> If you take the function with the gotos, and simplify the structure, it
>> looks like this:
.....

> The central mistake is that the the consturctor takes an empty structure 
> to fill in, rather than returning a pointer to an allocated structure. 
> Then the destructor itself can return an error.
> Change this, and you get
>
>     Init(a); if(x) goto f0;
>     Init(b); if(x) goto f0;
>     Init(c); if(x) goto f0;
>     Init(d); if(x) goto f0;
>
>     Set(b,3);  if(x) goto f0;
>
>     Free(d);
>     Free(c);
>     Free(b);
>     Free(a);
>     return(p);
>
> f0: Free(d);
>     Free(c);
>     Free(b);
>     Free(a);
>     return(q);
>
> That's much mpre acceptable. The control flow is still doiminated by 
> gotos, but that's because all the calls can return errors, which go into a 
> single error handler.

Yes. And now the two blocks of Frees are almost identical, and they can be 
combined into one. At that point you'll probably change the initialisation 
to be something like:

 if (Init(a) && Init(b) ... )
   Set(b,3);
 Free(d);
 ...

However there is the requirement to return one of several error codes, 
either from the first failing Init(), from a failing Set(), or from a first 
failing Free() (but in case of a failure here, all remaining objects must 
still be freed).

It's this elevating the importance of an error return far above that of any 
actual results, that is causing the difficulties. The design needs more work 
to make it easier to manage allocation and returns, otherwise programming 
anything non-trivial (or even trivial!) will be impossible.

-- 
Bartc 

0
Reply bc (2221) 6/9/2012 3:12:51 PM

=D7=91=D7=AA=D7=90=D7=A8=D7=99=D7=9A =D7=99=D7=95=D7=9D =D7=A9=D7=91=D7=AA,=
 9 =D7=91=D7=99=D7=95=D7=A0=D7=99 2012 16:12:51 UTC+1, =D7=9E=D7=90=D7=AA B=
art:
> "Malcolm McLean" <malcolm.mclean5@btinternet.com> wrote in message=20
>=20
> However there is the requirement to return one of several error codes,=20
> either from the first failing Init(), from a failing Set(), or from a fir=
st=20
> failing Free() (but in case of a failure here, all remaining objects must=
=20
> still be freed).
>
Usually two things can go wrong. Either there was a programming error, or t=
he
 computer ran out of memory.

If there's a programming error, fundamentally there's nothing good you can =
do.
 If the computer ran out of memory, usually that indicates a programming er=
ror
 (sensible integers can't exceed the memory capacity of a 4gigabyte machine=
).
 The problem with C is that you have to handle and report the situation.
>=20
> It's this elevating the importance of an error return far above that of a=
ny=20
> actual results, that is causing the difficulties. The design needs more w=
ork=20
> to make it easier to manage allocation and returns, otherwise programming=
=20
> anything non-trivial (or even trivial!) will be impossible.
>=20
C doesn't distinguish between error processing and the normal control paths=
..
 But you can keep such a distinction, by defing a label error_exit; Once
 you've jumped to that able, the program is in error state. Generally you
 need to pass up error returns through the call stack, until some function
 knows whether it's better to suppress the error, inform the user, or termi=
nate.
0
Reply malcolm.mclean5 (750) 6/9/2012 3:44:26 PM

"Malcolm McLean" <malcolm.mclean5@btinternet.com> ha scritto nel messaggio 
news:7d436013-af84-4200-a84e-06064eac46fe@googlegroups.com...
?????? ??? ???, 9 ????? 2012 16:12:51 UTC+1, ??? Bart:
> "Malcolm McLean" <malcolm.mclean5@btinternet.com> wrote in message
>
> However there is the requirement to return one of several error codes,
> either from the first failing Init(), from a failing Set(), or from a first
> failing Free() (but in case of a failure here, all remaining objects must
> still be freed).
>
Usually two things can go wrong. Either there was a programming error, or the
 computer ran out of memory.

If there's a programming error, fundamentally there's nothing good you can do.

#but i know *there is some error* for correct it, and where the error is...
#i make errors, it is for this, each single bit for find-correct error is good
#is not a .exe space problem, not a time problem...
#but possibly all you not make errors, so not have the need to
#find-correct them...

 If the computer ran out of memory, usually that indicates a programming error
 (sensible integers can't exceed the memory capacity of a 4gigabyte machine).

 The problem with C is that you have to handle and report the situation.


0
Reply io_x 6/10/2012 4:23:18 PM

In article <jqu4js$ovs$1@dont-email.me>, BartC <bc@freeuk.com> wrote:
>    Init(a); if(x) goto f0;
>    Init(b); if(x) goto f1;
>    Init(c); if(x) goto f2;
>    Init(d); if(x) goto f3;
>
>    Set(b,3);  if(x) goto f4;
>
>    Free(d); if(x) goto f3;
>    Free(c); if(x) goto f2;
>    Free(b); if(x) goto f1;
>    Free(a); if(x) goto f0;
>    return(p);
>
>f4: Free(d);
>f3: Free(c);
>f2: Free(b);
>f1: Free(a);
>f0:
>    return(q);

Excellent!  Thanks!

I think you just showed how to write good code.
0
Reply jgk1 (176) 6/10/2012 4:56:14 PM

"io_x" <a@b.c.invalid> ha scritto nel messaggio
news:4fd4c8a8$0$1389$4fafbaef@reader2.news.tin.it...
>
> "Malcolm McLean" <malcolm.mclean5@btinternet.com> ha scritto nel messaggio
> news:7d436013-af84-4200-a84e-06064eac46fe@googlegroups.com...
> ?????? ??? ???, 9 ????? 2012 16:12:51 UTC+1, ??? Bart:
>> "Malcolm McLean" <malcolm.mclean5@btinternet.com> wrote in message
>>
>> However there is the requirement to return one of several error codes,
>> either from the first failing Init(), from a failing Set(), or from a first
>> failing Free() (but in case of a failure here, all remaining objects must
>> still be freed).
>>
> Usually two things can go wrong. Either there was a programming error, or the
> computer ran out of memory.
>
> If there's a programming error, fundamentally there's nothing good you can do.

possibly i not understand well
yes in the big num library i use, in C++ language
i have not a way for find errors
for example what to do if i have

num  x,y,z,t, tmp;

x=(x+3)*z*t;

and the only error can occur, or can be seen or catch, it is the out of memory
error ...
so what you say it is what i thought: are you a mind reader?

in case of out of memory error here the program should exit from above...
[constructor of x, z, etc if malloc return null exit(), the same
* and + if the num can not be allocated exit()]

asm routine that calulate operations on x, z, t can find some arg error
or possibly other errors, but i never find a way for use the information
in the C++ language side at last in compose operations...

so: could be useful find error even if the only cachable errors are the
ones of out of memory errors?

is there someone from all you that know what i can do for find error
without exceptions in the big num library?

i find a way, some little add of code in each assembly functions
and some space in each number...but i don't know if could be ok
or could be usefull...

> #but i know *there is some error* for correct it, and where the error is...
> #i make errors, it is for this, each single bit for find-correct error is good
> #is not a .exe space problem, not a time problem...
> #but possibly all you not make errors, so not have the need to
> #find-correct them...
>
> If the computer ran out of memory, usually that indicates a programming error
> (sensible integers can't exceed the memory capacity of a 4gigabyte machine).
>
> The problem with C is that you have to handle and report the situation.
>
>



0
Reply io_x 6/10/2012 5:42:37 PM

On Sunday, June 10, 2012 5:23:18 PM UTC+1, io_x wrote:
> "Malcolm McLean" <malcolm.mclean5@btinternet.com> ha scritto nel messaggio 
> news:7d436013-af84-4200-a84e-06064eac46fe@googlegroups.com...

<snip>

against my better judgement I'm goign to try a decode one of io_x's posts

> Usually two things can go wrong. Either there was a programming error, or the
>  computer ran out of memory.
> 
> If there's a programming error, fundamentally there's nothing good you can do.
> 
> #but i know *there is some error* for correct it, and where the error is...
> #i make errors, it is for this, each single bit for find-correct error is good
> #is not a .exe space problem, not a time problem...
> #but possibly all you not make errors, so not have the need to
> #find-correct them...

are you trying to say something like this:-

"but even in the case of a programming error a good diagnostic 
will tell you at least where the error occurred; and the more 
information that can be provided the easier it is to track down 
the root cause. Perhaps the rest of you don't make programming errors!"

if so I have some sympathy. The humble assert() should not be neglected.
Perhaps your unit tests need to be improved?
0
Reply nick_keighley_nospam (4575) 6/11/2012 8:14:47 AM

Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
> jgk@panix.com (Joe keane) writes:
> 
> > In article <0.ad98122c5f4b9fe6aef5.20120602154227BST.87aa0lepws.fsf@bsb.me.uk>,
> > Ben Bacarisse  <ben.usenet@bsb.me.uk> wrote:
> >>I like allocation functions that return NULL on failure.
> >
> > I like allocation functions that set the carry bit on failure.
> 
> I wish you and the carry bit all the best.

What carry bit? I've searched high and low on my poor old Alpha, 
and can't find one.

Phil
-- 
> I'd argue that there is much evidence for the existence of a God.
Pics or it didn't happen.
-- Tom (/. uid 822)
0
Reply thefatphil_demunged (1562) 6/11/2012 3:10:58 PM

Phil Carmody <thefatphil_demunged@yahoo.co.uk> writes:

> Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
>> jgk@panix.com (Joe keane) writes:
>> 
>> > In article <0.ad98122c5f4b9fe6aef5.20120602154227BST.87aa0lepws.fsf@bsb.me.uk>,
>> > Ben Bacarisse  <ben.usenet@bsb.me.uk> wrote:
>> >>I like allocation functions that return NULL on failure.
>> >
>> > I like allocation functions that set the carry bit on failure.
>> 
>> I wish you and the carry bit all the best.
>
> What carry bit? I've searched high and low on my poor old Alpha, 
> and can't find one.

Why are you asking me?

-- 
Ben.
0
Reply ben.usenet (6516) 6/11/2012 3:19:33 PM

In article <538a3102-833f-4a0b-a790-733cc91629fa@googlegroups.com>,
Malcolm McLean  <malcolm.mclean5@btinternet.com> wrote:
>     Init(a); if(x) goto f0;
>     Init(b); if(x) goto f0;
>     Init(c); if(x) goto f0;
>     Init(d); if(x) goto f0;
> 
>     Set(b,3);  if(x) goto f0;
> 
>     Free(d); 
>     Free(c); 
>     Free(b); 
>     Free(a);
>     return(p);
> 
> f0: Free(d);
>     Free(c);
>     Free(b);
>     Free(a);
>     return(q);

This code looks wrong.

If 'Init(a)' fails, then we go to 'Free(d)'?

I'm sure that you can make it work, somehow.

My point is that error handling is not that hard: if some 'allocate'
fails we go to the 'unallocate' of the previous one.

If you follow this rule, you should have correct code.

If you try to get 'clever' about it, that's when mistakes slip in.
Mistakes in error handling suck.
0
Reply jgk1 (176) 6/11/2012 5:24:40 PM


"Joe keane" <jgk@panix.com> wrote in message
news:jr59ko$443$1@reader1.panix.com...
> In article <538a3102-833f-4a0b-a790-733cc91629fa@googlegroups.com>,
> Malcolm McLean  <malcolm.mclean5@btinternet.com> wrote:
>>     Init(a); if(x) goto f0;
>>     Init(b); if(x) goto f0;
>>     Init(c); if(x) goto f0;
>>     Init(d); if(x) goto f0;
>>
>>     Set(b,3);  if(x) goto f0;
>>
>>     Free(d);
>>     Free(c);
>>     Free(b);
>>     Free(a);
>>     return(p);
>>
>> f0: Free(d);
>>     Free(c);
>>     Free(b);
>>     Free(a);
>>     return(q);
>
> This code looks wrong.
>
> If 'Init(a)' fails, then we go to 'Free(d)'?
>
> I'm sure that you can make it work, somehow.

I think the idea was that an unconditional Free() is used, where it knows
(even without a formal Init()) whether a particular object needs freeing. 
(For example, where an object is a pointer set to NULL.)

> My point is that error handling is not that hard: if some 'allocate'
> fails we go to the 'unallocate' of the previous one.

But the logic for that can become labyrinthic. (Eg. suppose each of the
previous Inits() were conditional, or initialised in an different order each 
time?)

There are other approaches to just freeing everything on exit; perhaps each
Init() can add an object to a local list of objects that need freeing, then
only those need to be checked on a common exit. This is useful where there
are large numbers of objects of which only some might be active at any time,
or it fails early on.

> If you try to get 'clever' about it, that's when mistakes slip in.
> Mistakes in error handling suck.

Have a look at the OP's original code: the one with gotos, and the one
without. The latter especially is quite long-winded, and likely to be more
error-prone that something a lot shorter.

-- 
Bartc 

0
Reply bc (2221) 6/11/2012 6:02:22 PM

<nick_keighley_nospam@hotmail.com> ha scritto nel messaggio 
news:8c647bfc-4310-4d17-91df-6523923a51f2@googlegroups.com...
> On Sunday, June 10, 2012 5:23:18 PM UTC+1, io_x wrote:
>> "Malcolm McLean" <malcolm.mclean5@btinternet.com> ha scritto nel messaggio
>> news:7d436013-af84-4200-a84e-06064eac46fe@googlegroups.com...
>
> <snip>
>
> against my better judgement I'm goign to try a decode one of io_x's posts
>
>> Usually two things can go wrong. Either there was a programming error, or the
>>  computer ran out of memory.
>>
>> If there's a programming error, fundamentally there's nothing good you can 
>> do.
>>
>> #but i know *there is some error* for correct it, and where the error is...
>> #i make errors, it is for this, each single bit for find-correct error is 
>> good
>> #is not a .exe space problem, not a time problem...
>> #but possibly all you not make errors, so not have the need to
>> #find-correct them...
>
> are you trying to say something like this:-
>
> "but even in the case of a programming error a good diagnostic
> will tell you at least where the error occurred;

the error occurred and where; the problem is one presumible little
slow down... but if someone search for error search in memory allready
load or that has to be load for doing the calculation

> and the more
> information that can be provided the easier it is to track down
> the root cause. Perhaps the rest of you don't make programming errors!"
>
> if so I have some sympathy. The humble assert() should not be neglected.
> Perhaps your unit tests need to be improved?

i not use assert()


0
Reply io_x 6/12/2012 6:01:09 AM

<nick_keighley_nospam@hotmail.com> ha scritto nel messaggio
news:8c647bfc-4310-4d17-91df-6523923a51f2@googlegroups.com...
> if so I have some sympathy. The humble assert() should not be neglected.
> Perhaps your unit tests need to be improved?

yes for unit test; i'm implementing the first only now...
but it do not a full test, some routine not too much long
for see if something it is wrong...

for assert:
i see in this way
from this function

int  fun(void*  p)
{// define new varibles

 assert(p!=NULL);
 ....
}

i always prefer:
int  fun(void*  p)
{// define new varibles

 if(p==NULL)  return -1;
 ....
}

it is because it is not fun() that has to work with the error
but it is the function that call fun()
it seem recursive...
this is the only reason i have for think that



0
Reply io_x 6/12/2012 6:44:57 AM

On Tuesday, June 12, 2012 7:01:09 AM UTC+1, io_x wrote:
> <nick_keighley_nospam@hotmail.com> ha scritto nel messaggio 
> news:8c647bfc-4310-4d17-91df-6523923a51f2@googlegroups.com...
> > On Sunday, June 10, 2012 5:23:18 PM UTC+1, io_x wrote:
> >> "Malcolm McLean" <malcolm.mclean5@btinternet.com> ha scritto nel messaggio
> >> news:7d436013-af84-4200-a84e-06064eac46fe@googlegroups.com...

> > against my better judgement I'm goign to try a decode one of io_x's posts
> >
> >> Usually two things can go wrong. Either there was a programming error, 
> >> or the computer ran out of memory.
> >>
> >> If there's a programming error, fundamentally there's nothing good you can 
> >> do.
> >>
> >> #but i know *there is some error* for correct it, and where the error is...
> >> #i make errors, it is for this, each single bit for find-correct error is 
> >> good
> >> #is not a .exe space problem, not a time problem...
> >> #but possibly all you not make errors, so not have the need to
> >> #find-correct them...
> >
> > are you trying to say something like this:-
> >
> > "but even in the case of a programming error a good diagnostic
> > will tell you at least where the error occurred;
> 
> the error occurred and where; the problem is one presumible little
> slow down...

"it may slow the program down a little"?

> but if someone search for error search in memory allready
> load or that has to be load for doing the calculation

sorry I haven't taken the advanced class in gibberish!

> > and the more
> > information that can be provided the easier it is to track down
> > the root cause. Perhaps the rest of you don't make programming errors!"
> >
> > if so I have some sympathy. The humble assert() should not be neglected.
> > Perhaps your unit tests need to be improved?
> 
> i not use assert()

no surprise!
0
Reply nick_keighley_nospam (4575) 6/12/2012 12:27:24 PM

In article <jr5brl$i6r$1@dont-email.me>, BartC <bc@freeuk.com> wrote:
>Have a look at the OP's original code: the one with gotos, and the one
>without. The latter especially is quite long-winded, and likely to be more
>error-prone that something a lot shorter.

I think we're violently in agreement here: trying to make code
goto-free, because 'all gotos are evil', results in code that is more
bulky and more error-prone.
0
Reply jgk1 (176) 6/12/2012 8:03:00 PM

On Tuesday, June 12, 2012 9:03:00 PM UTC+1, Joe keane wrote:
> In article <jr5brl$i6r$1@dont-email.me>, BartC <bc@freeuk.com> wrote:

> >Have a look at the OP's original code: the one with gotos, and the one
> >without. The latter especially is quite long-winded, and likely to be more
> >error-prone that something a lot shorter.
> 
> I think we're violently in agreement here: trying to make code
> goto-free, because 'all gotos are evil', results in code that is more
> bulky and more error-prone.

you may be in agreement but many posters on this thread are not.
(just when did "evil" become a fashionable word to use in programming? And why?)
0
Reply nick_keighley_nospam (4575) 6/13/2012 7:58:52 AM

On 06/13/2012 03:58 AM, nick_keighley_nospam@hotmail.com wrote:
> On Tuesday, June 12, 2012 9:03:00 PM UTC+1, Joe keane wrote:
>> In article <jr5brl$i6r$1@dont-email.me>, BartC <bc@freeuk.com> wrote:
> 
>>> Have a look at the OP's original code: the one with gotos, and the one
>>> without. The latter especially is quite long-winded, and likely to be more
>>> error-prone that something a lot shorter.
>>
>> I think we're violently in agreement here: trying to make code
>> goto-free, because 'all gotos are evil', results in code that is more
>> bulky and more error-prone.
> 
> you may be in agreement but many posters on this thread are not.
> (just when did "evil" become a fashionable word to use in programming? And why?)

According to groups.google.com, the first use of 'evil' in the comp.*
hierarchy was on 1986-11-09, just 13 days after the first message posted
to that hierarchy. I think it was already fashionable at that time, but
I don't know any easy way to determine when that happened.
-- 
James Kuyper
0
Reply jameskuyper (5207) 6/13/2012 10:37:26 AM

On Wednesday, June 13, 2012 11:37:26 AM UTC+1, James Kuyper wrote:
> On 06/13/2012 03:58 AM, nick_keighley_nospam@hotmail.com wrote:

<snip>

> > (just when did "evil" become a fashionable word to use in 
> > programming? And why?)
> 
> According to groups.google.com, the first use of 'evil' in the comp.*
> hierarchy was on 1986-11-09, just 13 days after the first message posted
> to that hierarchy. I think it was already fashionable at that time, but
> I don't know any easy way to determine when that happened.

ah so there is nothing new under the sun. I'd only recently encountered this usage (the C++ FAQ uses it a lot) so I assumed it was some "new fangled" thing. I'd use words like "ill-advised" or "indicitive of potential problems" but "evil" is shorter...

I have a similar teeth gritting reflex when I come across "code smell"
0
Reply nick_keighley_nospam (4575) 6/13/2012 11:50:34 AM

On Jun 13, 8:58=A0am, nick_keighley_nos...@hotmail.com wrote:

> you may be in agreement but many posters on this thread are not.
> (just when did "evil" become a fashionable word to use in programming? An=
d why?)

Looking at http://www.catb.org/jargon/oldversions/ it makes it into
the Jargon File some time about revision 2.1.5 (November 1990).
0
Reply gwowen (532) 6/13/2012 2:02:22 PM

nick_keighley_nospam@hotmail.com wrote:
> On Tuesday, June 12, 2012 9:03:00 PM UTC+1, Joe keane wrote:
>> In article <jr5brl$i6r$1@dont-email.me>, BartC <bc@freeuk.com> wrote:
>
>>> Have a look at the OP's original code: the one with gotos, and the one
>>> without. The latter especially is quite long-winded, and likely to be more
>>> error-prone that something a lot shorter.
>>
>> I think we're violently in agreement here: trying to make code
>> goto-free, because 'all gotos are evil', results in code that is more
>> bulky and more error-prone.
>
> you may be in agreement but many posters on this thread are not.
> (just when did "evil" become a fashionable word to use in programming? And why?)
>

When people stopped thinking about it. Any use of the word "evil" is a
signal that the speaker has stopped thinking about it.

--
Les Cargill

0
Reply lcargill991 (446) 6/13/2012 5:47:52 PM

On 06/13/2012 01:47 PM, Les Cargill wrote:
> nick_keighley_nospam@hotmail.com wrote:
>> On Tuesday, June 12, 2012 9:03:00 PM UTC+1, Joe keane wrote:
>>> In article <jr5brl$i6r$1@dont-email.me>, BartC <bc@freeuk.com> wrote:
>>
>>>> Have a look at the OP's original code: the one with gotos, and the one
>>>> without. The latter especially is quite long-winded, and likely to be more
>>>> error-prone that something a lot shorter.
>>>
>>> I think we're violently in agreement here: trying to make code
>>> goto-free, because 'all gotos are evil', results in code that is more
>>> bulky and more error-prone.
>>
>> you may be in agreement but many posters on this thread are not.
>> (just when did "evil" become a fashionable word to use in programming? And why?)
>>
> 
> When people stopped thinking about it. Any use of the word "evil" is a
> signal that the speaker has stopped thinking about it.

You just used that word. :-)

There's nothing wrong with stopping thinking about something, so long as
you've completed your thinking about it, and have moved on to thinking
about something else. I think perhaps you intended to say something like
"... has not given sufficient thought to it."
If so, I would disagree - I think it's perfectly possible to give
sufficient thought to something, and come to the conclusion that it can
be described as "evil". It's a normative judgement, and as such
inherently subjective, but no more or less so than "good".
0
Reply jameskuyper (5207) 6/13/2012 6:17:36 PM

nick_keighley_nospam@hotmail.com writes:

> you may be in agreement but many posters on this thread are not.
> (just when did "evil" become a fashionable word to use in programming? 
> And why?

Why? Because "considered harmful" took too long to type.
0
Reply gwowen (532) 6/13/2012 6:57:28 PM

James Kuyper wrote:
) On 06/13/2012 01:47 PM, Les Cargill wrote:
)> When people stopped thinking about it. Any use of the word "evil" is a
)> signal that the speaker has stopped thinking about it.
)
) You just used that word. :-)
)
) There's nothing wrong with stopping thinking about something, so long as
) you've completed your thinking about it, and have moved on to thinking
) about something else. I think perhaps you intended to say something like
) "... has not given sufficient thought to it."
) If so, I would disagree - I think it's perfectly possible to give
) sufficient thought to something, and come to the conclusion that it can
) be described as "evil". It's a normative judgement, and as such
) inherently subjective, but no more or less so than "good".

To paraphrase:

" I think you meant to say something else, which I disagree
  with, however I do agree with what you actually said. "

Debate club much?


SaSW, Willem
-- 
Disclaimer: I am in no way responsible for any of the statements
            made in the above text. For all I know I might be
            drugged or something..
            No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
0
Reply willem6 (255) 6/13/2012 7:44:18 PM

On 06/13/2012 03:44 PM, Willem wrote:
> James Kuyper wrote:
> ) On 06/13/2012 01:47 PM, Les Cargill wrote:
> )> When people stopped thinking about it. Any use of the word "evil" is a
> )> signal that the speaker has stopped thinking about it.
> )
> ) You just used that word. :-)
> )
> ) There's nothing wrong with stopping thinking about something, so long as
> ) you've completed your thinking about it, and have moved on to thinking
> ) about something else. I think perhaps you intended to say something like
> ) "... has not given sufficient thought to it."
> ) If so, I would disagree - I think it's perfectly possible to give
> ) sufficient thought to something, and come to the conclusion that it can
> ) be described as "evil". It's a normative judgement, and as such
> ) inherently subjective, but no more or less so than "good".
> 
> To paraphrase:
> 
> " I think you meant to say something else, which I disagree
>   with, however I do agree with what you actually said. "

If he meant what he actually said, there was little point in saying it,
at least in this context. If my guess about what he meant to say is
correct, there was a point in saying it, at least from the point of view
of someone who believes it to be true. I've heard similar sentiments
expressed before, often enough to justify considering the possibility
that it is indeed what he meant to say.
0
Reply jameskuyper (5207) 6/13/2012 7:52:28 PM

James Kuyper wrote:
> On 06/13/2012 01:47 PM, Les Cargill wrote:
>> nick_keighley_nospam@hotmail.com wrote:
>>> On Tuesday, June 12, 2012 9:03:00 PM UTC+1, Joe keane wrote:
>>>> In article <jr5brl$i6r$1@dont-email.me>, BartC <bc@freeuk.com> wrote:
>>>
>>>>> Have a look at the OP's original code: the one with gotos, and the one
>>>>> without. The latter especially is quite long-winded, and likely to be more
>>>>> error-prone that something a lot shorter.
>>>>
>>>> I think we're violently in agreement here: trying to make code
>>>> goto-free, because 'all gotos are evil', results in code that is more
>>>> bulky and more error-prone.
>>>
>>> you may be in agreement but many posters on this thread are not.
>>> (just when did "evil" become a fashionable word to use in programming? And why?)
>>>
>>
>> When people stopped thinking about it. Any use of the word "evil" is a
>> signal that the speaker has stopped thinking about it.
>
> You just used that word. :-)
>

AHHHHH! OH NOOOOOOO! :) < falls off the Bridge of Death >

> There's nothing wrong with stopping thinking about something, so long as
> you've completed your thinking about it, and have moved on to thinking
> about something else. I think perhaps you intended to say something like
> "... has not given sufficient thought to it."

Probably. I meant more like "let's just round it up to evil". Either
that, or I wanted it to be one of those pithy Malcolm Gladwell style
aphorisms.

> If so, I would disagree - I think it's perfectly possible to give
> sufficient thought to something, and come to the conclusion that it can
> be described as "evil". It's a normative judgement, and as such
> inherently subjective, but no more or less so than "good".
>

Anything that is commonly described as evil usually has a more or less
reasonable explanation behind it. Simply declaring it beyond 
understanding is, in my opinion, just not wanting to do your homework.

Granted, sometimes the homework is simply insurmountable. But it would
be, in my opinion, more honest to just say that.

If I had to just mark, say, the Dred Scott decision as simply
evil, I'd lose out on a lot of detail.

So it's a useful rule of thumb to me anyway.

--
Les Cargill
0
Reply lcargill991 (446) 6/13/2012 10:45:43 PM

On 06/13/2012 06:45 PM, Les Cargill wrote:
> James Kuyper wrote:
....
>> If so, I would disagree - I think it's perfectly possible to give
>> sufficient thought to something, and come to the conclusion that it can
>> be described as "evil". It's a normative judgement, and as such
>> inherently subjective, but no more or less so than "good".
>>
> 
> Anything that is commonly described as evil usually has a more or less
> reasonable explanation behind it. Simply declaring it beyond 
> understanding is, in my opinion, just not wanting to do your homework.

You equate describing something as "evil" with "declaring it beyond
understanding"? I don't. I can understand evil (not always, especially
in extreme cases - but often). I've wanted to commit evil, and have
occasionally failed to resist the temptation to do so. I understand why
others would be tempted to do evil, and why they sometimes give in.
There are many people whose acts have been far more evil than any that
I've ever committed or even been tempted to commit, but I'm intelligent
enough to extrapolate from my own experiences, with due attention to the
dangers of extrapolation. To me, calling something "evil" does not mark
it as beyond understanding, but only as seriously undesirable behavior,
whether or not it is well understood.
0
Reply jameskuyper (5207) 6/13/2012 11:07:04 PM

"io_x" <a@b.c.invalid> ha scritto nel messaggio
news:4fd4db70$0$1386$4fafbaef@reader2.news.tin.it...
> possibly i not understand well
> yes in the big num library i use, in C++ language
> i have not a way for find errors
> for example what to do if i have
>
> num  x,y,z,t, tmp;
>
> x=(x+3)*z*t;
>
> and the only error can occur, or can be seen or catch, it is the out of memory
> error ...
> so what you say it is what i thought: are you a mind reader?
>
> in case of out of memory error here the program should exit from above...
> [constructor of x, z, etc if malloc return null exit(), the same
> * and + if the num can not be allocated exit()]
>
> asm routine that calulate operations on x, z, t can find some arg error
> or possibly other errors,

i remembered wrong, my asm-big number routines have not error check...
possibly i wrote them before my obsession for find errors...
so all operation on big num will not report error, the only error is out
of memory

> but i never find a way for use the information
> in the C++ language side at last in compose operations...
>
> so: could be useful find error even if the only cachable errors are the
> ones of out of memory errors?
>
> is there someone from all you that know what i can do for find error
> without exceptions in the big num library?
>
> i find a way, some little add of code in each assembly functions
> and some space in each number...but i don't know if could be ok
> or could be usefull...





0
Reply io_x 6/14/2012 4:00:49 PM

In article <4FD8D940.7010700@verizon.net>,
James Kuyper  <jameskuyper@verizon.net> wrote:
>You just used that word. :-)

He mentioned it, the same as me.
0
Reply jgk1 (176) 6/14/2012 11:03:27 PM

On 2012-06-13, James Kuyper <jameskuyper@verizon.net> wrote:
> On 06/13/2012 01:47 PM, Les Cargill wrote:
>> When people stopped thinking about it. Any use of the word "evil" is a
>> signal that the speaker has stopped thinking about it.
>
> You just used that word. :-)

Yes, and from the way the paragraph concluded, it's evident he stopped thinking
about it.
0
Reply kaz15 (1129) 6/14/2012 11:25:05 PM

Kaz Kylheku wrote:
> On 2012-06-13, James Kuyper <jameskuyper@verizon.net> wrote:
>> On 06/13/2012 01:47 PM, Les Cargill wrote:
>>> When people stopped thinking about it. Any use of the word "evil" is a
>>> signal that the speaker has stopped thinking about it.
>>
>> You just used that word. :-)
>
> Yes, and from the way the paragraph concluded, it's evident he stopped thinking
> about it.
>


Stopped thinking about what?

--
Les Cargill

0
Reply lcargill991 (446) 6/15/2012 12:25:09 AM

Les Cargill=E6=96=BC 2012=E5=B9=B46=E6=9C=8815=E6=97=A5=E6=98=9F=E6=9C=9F=
=E4=BA=94UTC+8=E4=B8=8A=E5=8D=888=E6=99=8225=E5=88=8609=E7=A7=92=E5=AF=AB=
=E9=81=93=EF=BC=9A
> Kaz Kylheku wrote:
> > On 2012-06-13, James Kuyper <jameskuyper@verizon.net> wrote:
> >> On 06/13/2012 01:47 PM, Les Cargill wrote:
> >>> When people stopped thinking about it. Any use of the word "evil" is =
a
> >>> signal that the speaker has stopped thinking about it.
> >>
> >> You just used that word. :-)
> >
> > Yes, and from the way the paragraph concluded, it's evident he stopped =
thinking
> > about it.
> >
>=20
>=20
> Stopped thinking about what?
>=20
> --
> Les Cargill



Les Cargill=E6=96=BC 2012=E5=B9=B46=E6=9C=8815=E6=97=A5=E6=98=9F=E6=9C=9F=
=E4=BA=94UTC+8=E4=B8=8A=E5=8D=888=E6=99=8225=E5=88=8609=E7=A7=92=E5=AF=AB=
=E9=81=93=EF=BC=9A
> Kaz Kylheku wrote:
> > On 2012-06-13, James Kuyper <jameskuyper@verizon.net> wrote:
> >> On 06/13/2012 01:47 PM, Les Cargill wrote:
> >>> When people stopped thinking about it. Any use of the word "evil" is =
a
> >>> signal that the speaker has stopped thinking about it.
> >>
> >> You just used that word. :-)
> >
> > Yes, and from the way the paragraph concluded, it's evident he stopped =
thinking
> > about it.
> >
>=20
>=20
> Stopped thinking about what?
>=20
> --
> Les Cargill

Please read books about Turing machines and automata to understand
the principles in assembly  and C first.
0
Reply dihedral88888 (786) 6/18/2012 3:32:08 AM

> Les Cargill=E6=96=BC 2012=E5=B9=B46=E6=9C=8815=E6=97=A5=E6=98=9F=E6=9C=9F=
=E4=BA=94UTC+8=E4=B8=8A=E5=8D=888=E6=99=8225=E5=88=8609=E7=A7=92=E5=AF=AB=
=E9=81=93=EF=BC=9A
> > Kaz Kylheku wrote:
> > > On 2012-06-13, James Kuyper <jameskuyper@verizon.net> wrote:
> > >> On 06/13/2012 01:47 PM, Les Cargill wrote:

> > >>> When people stopped thinking about it. Any use of the word "evil" i=
s a
> > >>> signal that the speaker has stopped thinking about it.
> > >>
> > >> You just used that word. :-)
> > >
> > > Yes, and from the way the paragraph concluded, it's evident he stoppe=
d=20
> > > thinking about it.
> >=20
> > Stopped thinking about what?
>=20
> Please read books about Turing machines and automata to understand
> the principles in assembly  and C first.

you're kidding I assume?

- how do Turing machine shelp understand assembler or C?
- how do Turing machines help understand got?
- what does this have to do with the usage of the word "evil"?
0
Reply nick_keighley_nospam (4575) 6/18/2012 8:30:05 AM

nick_keighley_nospam@hotmail.com wrote:
>> Les Cargill於 2012年6月15日星期五UTC+8上午8時25分09秒寫道:
>>> Kaz Kylheku wrote:
>>>> On 2012-06-13, James Kuyper <jameskuyper@verizon.net> wrote:
>>>>> On 06/13/2012 01:47 PM, Les Cargill wrote:
>
>>>>>> When people stopped thinking about it. Any use of the word "evil" is a
>>>>>> signal that the speaker has stopped thinking about it.
>>>>>
>>>>> You just used that word. :-)
>>>>
>>>> Yes, and from the way the paragraph concluded, it's evident he stopped
>>>> thinking about it.
>>>
>>> Stopped thinking about what?
>>
>> Please read books about Turing machines and automata to understand
>> the principles in assembly  and C first.
>
> you're kidding I assume?
>
> - how do Turing machine shelp understand assembler or C?
> - how do Turing machines help understand got?
> - what does this have to do with the usage of the word "evil"?
>


Maybe I shoulda smileyed :)

--
Les Cargill


0
Reply lcargill991 (446) 6/18/2012 12:06:40 PM

140 Replies
50 Views

(page loaded in 1.909 seconds)


Reply: