RES: Strange problem with VC++ compiler because of goto

Thanks again tim,

the anonymous one i quoted who gave the divide by zero exactly said
the same thing have a global and turn it true or false

but also said that this kind of global is again looked down

saying one should never have globals that are not inside a proc and
local to a proc
usage of globals again lead to spaghetti code

i meant better not by any timing standards

the emitted assembly in that case looked like

cmp [count],32
conditional jmp #Address (start of else clause) one single
conditional statement



… <— no ugly unconditional jumps embedded here
start of else clause


retn

i know this again may not be a valid argument and some one reading
this code later may never be able to understand the assembly generated
by this code
or may never look it up in a debugger or disassembler

so the code by itself wasnt crap to be thrown away at sight but valid
enough that only thing it warrented was a different approach

some one was adamant enough parroting never use gotos when seeing the code
(actually i saw some one saying the same thing in one of the posts
above (never use gotos NEVER USE GOTOS) thats why i jumped in

thanks and regards

raj_r

ps borland compiler was clever enough :slight_smile: ?

On 5/17/07, Tim Roberts wrote:
> raj_r wrote:
> >
> > nothing more nothing less im not trying to advocate its usage
> > but definately there seems to be places where goto produces better code
>
> How do you define “better” in this case? If you mean “it runs in 12
> microseconds instead of 14 microseconds”, then you are focusing on the
> wrong metric.
>
>
> > the code some thing like
> >
> > if(count>=32)
> > {
> > //your code here
> > goto label
> > }
> > else
> > {
> > label:
> > // some other code
> > }
> >
> > is where i noticed goto merging the else clause into a single proc
> >
> > if should execute,else should execute and in some special cases if
> > should execute and else should also execute
>
> You’re saying that the Borland compiler happened to compile that
> intelligently, and that’s fine. The KEY point is that it probably would
> have compiled it just as intelligently if you had written it like this:
>
> bool bDoSecondPart = false;
> if( count >= 32 )
> {
> // your code here
> if( … )
> bDoSecondPart = true;
> }
> else
> bDoSecondPart = true;
>
> if( bDoSecondPart )
> {
> // some other code
> }
>
> and writing it that way makes the intent of the code much more explicit.
>
> –
> Tim Roberts, xxxxx@probo.com
> Providenza & Boekelheide, Inc.
>
>
> —
> Questions? First check the Kernel Driver FAQ at http://www.osronline.com/article.cfm?id=256
>
> To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer
>

> I encountered a kernel framework

library written by Walter Oney that, through the inclusion of a couple
of magic functions, makes C++ exception handling work in 98 and NT
kernel drivers.
Wow!
Is it available?

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Tim Roberts
Sent: Thursday, May 17, 2007 2:01 PM
To: Windows System Software Devs Interest List
Subject: Re: [ntdev] Strange problem with VC++ compiler because of goto

Maxim S. Shatskih wrote:

> You shouldn’t use gotos. Avoid them. In a world of exceptions and
> encapsulated init/deinit there is no need for gotos.
>

Kernel does not support C++ exceptions.

However, much to my surprise, it turns out this is not too hard to
implement. Through another client, I encountered a kernel framework
library written by Walter Oney that, through the inclusion of a couple
of magic functions, makes C++ exception handling work in 98 and NT
kernel drivers.

Personally, it scared me. I set it gently down and backed slowly
towards the door, but there was no denying that it did work.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

I agree with this usage model of goto. The only ugly part being
conditionally unwinding the past allocations.

RAII in C++ fixes exactly this problem. The idea behind RAII being that a
resource is stored behind an object where the resource is acquired in the
constructor of the object and released in its destructor. So the minute your
object leaves scope its safely released ( assuming release doesnt fail ).
The resource could be a spinlock, mutex, file, socket, memory. Bottomline,
you have complete independence in exiting the function from any spot.

It shouldnt be difficult implementing RAII in C. Maintain a stack per
function and for each successful “do” operation add its “undo” opearation to
the stack. Later instead of doing a “return n” do a “YOUR_RETURN n” which is
a macro that pops the stack clean and returns the required value.
Essentially this is nothing but the balanced paranthesis problem.

banks

“Paul Gardiner” wrote in message news:xxxxx@ntdev…
>I know one context where use of goto does seem to give more
> easily maintained code. This is when freeing allocated
> resources under error conditions in the absence of
> exception handling.
>
> This is the ugly version:
>
> {
> A *a;
> B *b;
> C *c;
> D *c;
>
> a = AllocateA();
> if(a == NULL)
> return FAILED;
>
> b = AllocateB();
> if(b == NULL)
> {
> FreeA(a);
> return FAILED;
> }
>
> c = AllocateC();
> if(c == NULL)
> {
> FreeA(a);
> FreeB(b);
> return FAILED;
> }
>
> d = AllocateD();
> if(d == NULL)
> {
> FreeA(a);
> FreeB(b);
> FreeC(c);
> return FAILED;
> }
>
> return SUCCESS;
> }
>
> See how you have to carefully arrange exactly the
> right deallocations for each failure. Its a real
> pain to add new allocations somewhere in such
> a sequence.
>
> Here is the prettier version:
>
> {
> A *a = NULL;
> B *b = NULL;
> C *c = NULL;
> D *c = NULL;
>
> a = AllocateA();
> if(a == NULL)
> return FAILED;
>
> b = AllocateB();
> if(b == NULL)
> goto failure;
>
> c = AllocateC();
> if(c == NULL)
> goto failure;
>
> d = AllocateD();
> if(d == NULL)
> goto failure;
>
> return SUCCESS;
>
> failure:
> FreeA(a);
> FreeB(b);
> FreeC(c);
> return FAILED;
> }
>

The ugly version is a party compared to one that features deeply nested
if statements.

mm

>> xxxxx@glidos.net 2007-05-17 18:29 >>>
I know one context where use of goto does seem to give more
easily maintained code. This is when freeing allocated
resources under error conditions in the absence of
exception handling.

This is the ugly version:

{
A *a;
B *b;
C *c;
D *c;

a = AllocateA();
if(a == NULL)
return FAILED;

b = AllocateB();
if(b == NULL)
{
FreeA(a);
return FAILED;
}

c = AllocateC();
if(c == NULL)
{
FreeA(a);
FreeB(b);
return FAILED;
}

d = AllocateD();
if(d == NULL)
{
FreeA(a);
FreeB(b);
FreeC(c);
return FAILED;
}

return SUCCESS;
}

See how you have to carefully arrange exactly the
right deallocations for each failure. Its a real
pain to add new allocations somewhere in such
a sequence.

Here is the prettier version:

{
A *a = NULL;
B *b = NULL;
C *c = NULL;
D *c = NULL;

a = AllocateA();
if(a == NULL)
return FAILED;

b = AllocateB();
if(b == NULL)
goto failure;

c = AllocateC();
if(c == NULL)
goto failure;

d = AllocateD();
if(d == NULL)
goto failure;

return SUCCESS;

failure:
FreeA(a);
FreeB(b);
FreeC(c);
return FAILED;
}


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

Since so many others have chimed in, I’ll offer mine, as well.

PVOID p1, p2, p3;
DWORD status = STATUS_SUCCESS;

if(STATUS_SUCCESS == status)
{
p1 = AllocateTheFirstThing();
if(NULL == p1)
{
status = STATUS_MEMORY_ALLOC_FAILURE;
}
}

if(STATUS_SUCCESS == status)
{
p2 = AllocateTheSecondThing();
if(NULL == p2)
{
status = STATUS_MEMORY_ALLOC_FAILURE;
}
}

if(STATUS_SUCCESS == status)
{
p3 = AllocateTheThirdThing();
if(NULL == p3)
{
status = STATUS_MEMORY_ALLOC_FAILURE;
}
}

if(STATUS_SUCCESS != status)
{
if(NULL != p1)
{
DeleteTheFirstThing(p1);
}
if(NULL != p2)
{
DeleteTheSecondThing(p2);
}
if(NULL != p3)
{
DeleteTheThirdThing(p3);
}
}

return status;

One clean up point, one return point, consistent syntax, if’s aren’t nested
too deeply. Is it the “One True StyleT”? I don’t think such a thing
exists.

Can it eliminate the fights over goto? Yes, unless you are determined to
have one anyway…

Phil

Philip D. Barila Windows DDK MVP
Seagate Technology LLC
(720) 684-1842
As if I need to say it: Not speaking for Seagate.

wrote in message news:xxxxx@ntdev…
> hi,
>
> the problem with multiple returns in a function (especially in larger
> ones) is often, that some resources which are acquired (most often later
> during a change of the code) in that function are not freed at exit of the
> function because of an early “return”.
>
> Therefore - after hard discussions - we have the rule in our larger
> projects that each larger function has to have a label - most often named
> "exitFunction: " or so - near the end of the function. And everybody has
> to use “goto exitFunction” to leave the function. After that label all
> resources must be freed. Of course you have to keep track there which
> resources are really acquired when you reach this part of the code.
>
> And I think that it is completely structured code although there are those
> “gotos” inside the code. We have this discussion about gotos again and
> again, but I discuss about coding guidelines since more than 35 years now.
> It is very hard for my colleagues to argue with me about that point :wink:
>
> – Reinhard

Oops, haven’t been an MVP for a couple of years. Sorry. Haven’t used
Outlook Express in a while, either. :slight_smile:

Phil

Philip D. Barila
Seagate Technology LLC
(720) 684-1842
As if I need to say it: Not speaking for Seagate.

“Phil Barila” wrote in message
news:xxxxx@ntdev…
> –
> Philip D. Barila Windows DDK MVP

Did they remove your MVP status for using DWORD? just kidding… =P

Phil Barila wrote:

Oops, haven’t been an MVP for a couple of years. Sorry. Haven’t used
Outlook Express in a while, either. :slight_smile:

Phil

Phil Barila wrote:

Since so many others have chimed in, I’ll offer mine, as well.

PVOID p1, p2, p3;
DWORD status = STATUS_SUCCESS;

if(STATUS_SUCCESS == status)
{
p1 = AllocateTheFirstThing();
if(NULL == p1)
{
status = STATUS_MEMORY_ALLOC_FAILURE;
}
}

if(STATUS_SUCCESS == status)
{
p2 = AllocateTheSecondThing();
if(NULL == p2)
{
status = STATUS_MEMORY_ALLOC_FAILURE;
}
}

if(STATUS_SUCCESS == status)
{
p3 = AllocateTheThirdThing();
if(NULL == p3)
{
status = STATUS_MEMORY_ALLOC_FAILURE;
}
}

if(STATUS_SUCCESS != status)
{
if(NULL != p1)
{
DeleteTheFirstThing(p1);
}
if(NULL != p2)
{
DeleteTheSecondThing(p2);
}
if(NULL != p3)
{
DeleteTheThirdThing(p3);
}
}

return status;

One clean up point, one return point, consistent syntax, if’s aren’t nested
too deeply. Is it the “One True StyleT”? I don’t think such a thing
exists.

Can it eliminate the fights over goto? Yes, unless you are determined to
have one anyway…

That’s another style we sometimes use (a C based project), but it seems
to get in a mess with more complicated cases.

In any case, I think the one with goto’s is easier to read (subjective
of course).

Isn’t it true that gotos have gotten a bad name merely because bad
programmers are prone to use them instead of thinking out the natural
structure of the program. For exception handling (in a language which
has no native support), isn’t goto the natural construct. And for
languages that have native exception handling, isn’t “throw” just
a goto of a diffent name.

We use similar approach and the rule is simpler: one return per function. It naturally leads to what you describe. I expected hard discussion but surprisingly, coworkers agreed with no problem. Probably because everybody of them already encountered a problem with overlooked return. Other reason is we use traces which print function name + parameters on entry and return value on leave. The label before leave trace is then natural.

Personally, I take returns in the middle of the function as an evil. It becomes apparent when somebody embeds return in the macro. Something like this:

#define CATCH_ERROR(Function) if (!Function) return

Best regards,

Michal Vodicka
UPEK, Inc.
[xxxxx@upek.com, http://www.upek.com]


From: xxxxx@lists.osr.com[SMTP:xxxxx@lists.osr.com] on behalf of xxxxx@ixos.de[SMTP:xxxxx@ixos.de]
Reply To: Windows System Software Devs Interest List
Sent: Friday, May 18, 2007 9:04 AM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] RES: Strange problem with VC++ compiler because of goto

hi,

the problem with multiple returns in a function (especially in larger ones) is often, that some resources which are acquired (most often later during a change of the code) in that function are not freed at exit of the function because of an early “return”.

Therefore - after hard discussions - we have the rule in our larger projects that each larger function has to have a label - most often named "exitFunction: " or so - near the end of the function. And everybody has to use “goto exitFunction” to leave the function. After that label all resources must be freed. Of course you have to keep track there which resources are really acquired when you reach this part of the code.

And I think that it is completely structured code although there are those “gotos” inside the code. We have this discussion about gotos again and again, but I discuss about coding guidelines since more than 35 years now. It is very hard for my colleagues to argue with me about that point :wink:

– Reinhard


Questions? First check the Kernel Driver FAQ at http://www.osronline.com/article.cfm?id=256

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer

> ----------

From: xxxxx@lists.osr.com[SMTP:xxxxx@lists.osr.com] on behalf of Paul Gardiner[SMTP:xxxxx@glidos.net]
Reply To: Windows System Software Devs Interest List
Sent: Friday, May 18, 2007 6:38 PM
To: Windows System Software Devs Interest List
Subject: Re: [ntdev] RES: Strange problem with VC++ compiler because of goto

Isn’t it true that gotos have gotten a bad name merely because bad
programmers are prone to use them instead of thinking out the natural
structure of the program. For exception handling (in a language which
has no native support), isn’t goto the natural construct. And for
languages that have native exception handling, isn’t “throw” just
a goto of a diffent name.

Agreed. The other reason why goto has a bad name are bad teachers. It is easier for them to say “goto is bad, never use it” than teach students how to use it properly and explain why.

Best regards,

Michal Vodicka
UPEK, Inc.
[xxxxx@upek.com, http://www.upek.com]

> One clean up point, one return point, consistent syntax, if’s aren’t nested

too deeply.

…and well-suited for copy-pasting each step :slight_smile:

Yes, a good style for some kinds of code.


Maxim Shatskih, Windows DDK MVP
StorageCraft Corporation
xxxxx@storagecraft.com
http://www.storagecraft.com

“Maxim S. Shatskih” wrote in message
news:xxxxx@ntdev…
>> One clean up point, one return point, consistent syntax, if’s aren’t
>> nested
>> too deeply.
>
> …and well-suited for copy-pasting each step :slight_smile:

:wink:

I don’t think I have any reall code that is quite as simple as the example,
but it’s worked out well here.

Ack’s to the notes that throw is a fancy goto, and that goto is just another
tool, and is useful when used well.

Phil

Philip D. Barila
Seagate Technology LLC
(720) 684-1842
As if I need to say it: Not speaking for Seagate.

I was told to avoid goto’s in Cobol in my past. Writing a non-trivial
program following that rule in Cobol-68 made me learn a lot about keeping
code clean and the flow obvious. It is a good idea to avoid goto’s until
you are certain that your understanding of computers and the operating
system environment under which you live has matured enough to avoid misusing
them. It is also like using C++ in the kernel. It can be done correctly,
but novices should not try it.


David J. Craig
Engineer, Sr. Staff Software Systems
Broadcom Corporation

“Michal Vodicka” wrote in message
news:xxxxx@ntdev…
> ----------
> From:
> xxxxx@lists.osr.com[SMTP:xxxxx@lists.osr.com]
> on behalf of Paul Gardiner[SMTP:xxxxx@glidos.net]
> Reply To: Windows System Software Devs Interest List
> Sent: Friday, May 18, 2007 6:38 PM
> To: Windows System Software Devs Interest List
> Subject: Re: [ntdev] RES: Strange problem with VC++ compiler because of
> goto
>
> Isn’t it true that gotos have gotten a bad name merely because bad
> programmers are prone to use them instead of thinking out the natural
> structure of the program. For exception handling (in a language which
> has no native support), isn’t goto the natural construct. And for
> languages that have native exception handling, isn’t “throw” just
> a goto of a diffent name.
>
Agreed. The other reason why goto has a bad name are bad teachers. It is
easier for them to say “goto is bad, never use it” than teach students how
to use it properly and explain why.

Best regards,

Michal Vodicka
UPEK, Inc.
[xxxxx@upek.com, http://www.upek.com]

If I have to do pure C (fortunately this is rare… :p), I like to do it
this way:

#include <malloc.h>
#include <memory.h>

struct _MyStruct
{

void *a;
void *b;
void *c;

};

typedef struct _MyStruct MyStruct;

int Initialize(MyStruct *pMyStruct);
void Release(MyStruct *pMyStruct);

int Initialize(MyStruct *pMyStruct)
{

if (pMyStruct != 0)
{

memset(pMyStruct, 0, sizeof(MyStruct));

pMyStruct->a = malloc(1000);
if (!pMyStruct->a)
{
Release(pMyStruct);
return 0;
}

pMyStruct->b = malloc(1000);
if (!pMyStruct->b)
{
Release(pMyStruct);
return 0;
}

pMyStruct->c = malloc(1000);
if (!pMyStruct->c)
{
Release(pMyStruct);
return 0;
}
}

return 1;

};

void Release(MyStruct *pMyStruct)
{
if (pMyStruct)
{
if (pMyStruct->a != 0)
{
free(pMyStruct->a);
}

if (pMyStruct->b != 0)
{
free(pMyStruct->b);
}

if (pMyStruct->c != 0)
{
free(pMyStruct->c);
}

memset(pMyStruct, 0, sizeof(MyStruct));

}
};

int main(int argc, char **argv)
{

MyStruct s;

Initialize(&s);

Release(&s);

}

I always encapsulate my resources allocations inside a structure, if I need
to add more I only need to modify two functions. You can of course factor
further since we have here several malloc(1000) which should in fact emanate
from another Initialize.

I have no goto, but I have several returns. In this case however it is hard
to miss the “release” before return because there is only one call to
release all. I try very hard to have functions as small as possible, big
functions => more bugs. This increases the number of functions and the
initial amount of work but, to my experience, reduces the amount of bugs.

The code has to respect some sort of symmetry and harmony. When your code is
symmetric and harmonic, your brain is going to repeat intuitively the
patterns it sees and this reduces the occurrence of bugs.

When you start to get

while(1)
{
if (blah)
{
If ()
{
Break;
}
Else
{
}
}
else
{
if ((p = malloc(1000)) != 0)
{
Return;
}
else
{
Continue;
}
Break;
}
}

You WILL have memory leaks and you WILL have bugs. It’s not a problem of
break, continue, return whatever unholy keyword it’s a problem of structure,
symmetry and harmony.



Edouard A.

> -----Original Message-----
> From: xxxxx@lists.osr.com [mailto:bounce-287215-
> xxxxx@lists.osr.com] On Behalf Of Michal Vodicka
> Sent: vendredi 18 mai 2007 19:27
> To: Windows System Software Devs Interest List
> Subject: RE: [ntdev] RES: Strange problem with VC++ compiler because of
> goto
>
> We use similar approach and the rule is simpler: one return per
> function. It naturally leads to what you describe. I expected hard
> discussion but surprisingly, coworkers agreed with no problem. Probably
> because everybody of them already encountered a problem with overlooked
> return. Other reason is we use traces which print function name +
> parameters on entry and return value on leave. The label before leave
> trace is then natural.
>
> Personally, I take returns in the middle of the function as an evil. It
> becomes apparent when somebody embeds return in the macro. Something
> like this:
>
> #define CATCH_ERROR(Function) if (!Function) return
>
> Best regards,
>
> Michal Vodicka
> UPEK, Inc.
> [xxxxx@upek.com, http://www.upek.com]
>
>
> > ----------
> > From: xxxxx@lists.osr.com[SMTP:bounce-287149-
> xxxxx@lists.osr.com] on behalf of
> xxxxx@ixos.de[SMTP:xxxxx@ixos.de]
> > Reply To: Windows System Software Devs Interest List
> > Sent: Friday, May 18, 2007 9:04 AM
> > To: Windows System Software Devs Interest List
> > Subject: RE:[ntdev] RES: Strange problem with VC++ compiler because
> of goto
> >
> > hi,
> >
> > the problem with multiple returns in a function (especially in larger
> ones) is often, that some resources which are acquired (most often
> later during a change of the code) in that function are not freed at
> exit of the function because of an early “return”.
> >
> > Therefore - after hard discussions - we have the rule in our larger
> projects that each larger function has to have a label - most often
> named "exitFunction: " or so - near the end of the function. And
> everybody has to use “goto exitFunction” to leave the function. After
> that label all resources must be freed. Of course you have to keep
> track there which resources are really acquired when you reach this
> part of the code.
> >
> > And I think that it is completely structured code although there are
> those “gotos” inside the code. We have this discussion about gotos
> again and again, but I discuss about coding guidelines since more than
> 35 years now. It is very hard for my colleagues to argue with me about
> that point :wink:
> >
> > – Reinhard
> >
> >
> > —
> > Questions? First check the Kernel Driver FAQ at
> http://www.osronline.com/article.cfm?id=256
> >
> > To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer
> >
>
> —
> Questions? First check the Kernel Driver FAQ at
> http://www.osronline.com/article.cfm?id=256
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer</memory.h></malloc.h>

My approach is very similar except of multiple returns. Why to unnecessarily repeat the same code?

BOOLEAN Initialize(MyStruct *pMyStruct) {
BOOLEAN InitReady = FALSE;

if (pMyStruct != NULL) {
memset(pMyStruct, 0, sizeof(MyStruct));

if ((pMyStruct->a = malloc(1000)) == NULL) {
goto Done;
}
if ((pMyStruct->b = malloc(1000)) == NULL) {
goto Done;
}
if ((pMyStruct->c = malloc(1000)) == NULL) {
goto Done;
}
InitReady = TRUE;
}
Done:
if (!InitReady) {
Release(pMyStruct);
}
return(InitReady);
}

This is generic approach not related to allocations only. In such a simple case I’d use more structured form of goto:

BOOLEAN Initialize(MyStruct *pMyStruct) {
BOOLEAN InitReady = FALSE;

do {

if (pMyStruct == NULL) {
break;
}
memset(pMyStruct, 0, sizeof(MyStruct));

if ((pMyStruct->a = malloc(1000)) == NULL) {
break;
}
if ((pMyStruct->b = malloc(1000)) == NULL) {
break;
}
if ((pMyStruct->c = malloc(1000)) == NULL) {
break;
}
InitReady = TRUE;
} while (FALSE);

if (!InitReady) {
Release(pMyStruct);
}

return(InitReady);
}

Best regards,

Michal Vodicka
UPEK, Inc.
[xxxxx@upek.com, http://www.upek.com]


From: xxxxx@lists.osr.com[SMTP:xxxxx@lists.osr.com] on behalf of Edouard A.[SMTP:xxxxx@fausse.info]
Reply To: Windows System Software Devs Interest List
Sent: Friday, May 18, 2007 10:15 PM
To: Windows System Software Devs Interest List
Subject: RE: [ntdev] RES: Strange problem with VC++ compiler because of goto

If I have to do pure C (fortunately this is rare… :p), I like to do it
this way:

#include <malloc.h>
> #include <memory.h>
>
> struct _MyStruct
> {
>
> void *a;
> void *b;
> void *c;
>
> };
>
> typedef struct _MyStruct MyStruct;
>
> int Initialize(MyStruct *pMyStruct);
> void Release(MyStruct *pMyStruct);
>
> int Initialize(MyStruct *pMyStruct)
> {
>
> if (pMyStruct != 0)
> {
>
> memset(pMyStruct, 0, sizeof(MyStruct));
>
> pMyStruct->a = malloc(1000);
> if (!pMyStruct->a)
> {
> Release(pMyStruct);
> return 0;
> }
>
> pMyStruct->b = malloc(1000);
> if (!pMyStruct->b)
> {
> Release(pMyStruct);
> return 0;
> }
>
> pMyStruct->c = malloc(1000);
> if (!pMyStruct->c)
> {
> Release(pMyStruct);
> return 0;
> }
> }
>
> return 1;
>
> };
>
> void Release(MyStruct *pMyStruct)
> {
> if (pMyStruct)
> {
> if (pMyStruct->a != 0)
> {
> free(pMyStruct->a);
> }
>
> if (pMyStruct->b != 0)
> {
> free(pMyStruct->b);
> }
>
> if (pMyStruct->c != 0)
> {
> free(pMyStruct->c);
> }
>
> memset(pMyStruct, 0, sizeof(MyStruct));
>
> }
> };
>
> int main(int argc, char **argv)
> {
>
> MyStruct s;
>
> Initialize(&s);
>
> Release(&s);
>
> }
>
> I always encapsulate my resources allocations inside a structure, if I need
> to add more I only need to modify two functions. You can of course factor
> further since we have here several malloc(1000) which should in fact emanate
> from another Initialize.
>
> I have no goto, but I have several returns. In this case however it is hard
> to miss the “release” before return because there is only one call to
> release all. I try very hard to have functions as small as possible, big
> functions => more bugs. This increases the number of functions and the
> initial amount of work but, to my experience, reduces the amount of bugs.
>
> The code has to respect some sort of symmetry and harmony. When your code is
> symmetric and harmonic, your brain is going to repeat intuitively the
> patterns it sees and this reduces the occurrence of bugs.
>
> When you start to get
>
> while(1)
> {
> if (blah)
> {
> If ()
> {
> Break;
> }
> Else
> {
> }
> }
> else
> {
> if ((p = malloc(1000)) != 0)
> {
> Return;
> }
> else
> {
> Continue;
> }
> Break;
> }
> }
>
> You WILL have memory leaks and you WILL have bugs. It’s not a problem of
> break, continue, return whatever unholy keyword it’s a problem of structure,
> symmetry and harmony.
>
> –
>
> Edouard A.
>
>
> > -----Original Message-----
> > From: xxxxx@lists.osr.com [mailto:bounce-287215-
> > xxxxx@lists.osr.com] On Behalf Of Michal Vodicka
> > Sent: vendredi 18 mai 2007 19:27
> > To: Windows System Software Devs Interest List
> > Subject: RE: [ntdev] RES: Strange problem with VC++ compiler because of
> > goto
> >
> > We use similar approach and the rule is simpler: one return per
> > function. It naturally leads to what you describe. I expected hard
> > discussion but surprisingly, coworkers agreed with no problem. Probably
> > because everybody of them already encountered a problem with overlooked
> > return. Other reason is we use traces which print function name +
> > parameters on entry and return value on leave. The label before leave
> > trace is then natural.
> >
> > Personally, I take returns in the middle of the function as an evil. It
> > becomes apparent when somebody embeds return in the macro. Something
> > like this:
> >
> > #define CATCH_ERROR(Function) if (!Function) return
> >
> > Best regards,
> >
> > Michal Vodicka
> > UPEK, Inc.
> > [xxxxx@upek.com, http://www.upek.com]
> >
> >
> > > ----------
> > > From: xxxxx@lists.osr.com[SMTP:bounce-287149-
> > xxxxx@lists.osr.com] on behalf of
> > xxxxx@ixos.de[SMTP:xxxxx@ixos.de]
> > > Reply To: Windows System Software Devs Interest List
> > > Sent: Friday, May 18, 2007 9:04 AM
> > > To: Windows System Software Devs Interest List
> > > Subject: RE:[ntdev] RES: Strange problem with VC++ compiler because
> > of goto
> > >
> > > hi,
> > >
> > > the problem with multiple returns in a function (especially in larger
> > ones) is often, that some resources which are acquired (most often
> > later during a change of the code) in that function are not freed at
> > exit of the function because of an early “return”.
> > >
> > > Therefore - after hard discussions - we have the rule in our larger
> > projects that each larger function has to have a label - most often
> > named "exitFunction: " or so - near the end of the function. And
> > everybody has to use “goto exitFunction” to leave the function. After
> > that label all resources must be freed. Of course you have to keep
> > track there which resources are really acquired when you reach this
> > part of the code.
> > >
> > > And I think that it is completely structured code although there are
> > those “gotos” inside the code. We have this discussion about gotos
> > again and again, but I discuss about coding guidelines since more than
> > 35 years now. It is very hard for my colleagues to argue with me about
> > that point :wink:
> > >
> > > – Reinhard
> > >
> > >
> > > —
> > > Questions? First check the Kernel Driver FAQ at
> > http://www.osronline.com/article.cfm?id=256
> > >
> > > To unsubscribe, visit the List Server section of OSR Online at
> > http://www.osronline.com/page.cfm?name=ListServer
> > >
> >
> > —
> > Questions? First check the Kernel Driver FAQ at
> > http://www.osronline.com/article.cfm?id=256
> >
> > To unsubscribe, visit the List Server section of OSR Online at
> > http://www.osronline.com/page.cfm?name=ListServer
>
>
> —
> Questions? First check the Kernel Driver FAQ at http://www.osronline.com/article.cfm?id=256
>
> To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer
></memory.h></malloc.h>

If you don’t want to repeat, you can do it like this:

int Initialize(MyStruct *pMyStruct)
{

int iResult = 0;

if (pMyStruct != 0)
{

memset(pMyStruct, 0, sizeof(MyStruct));

pMyStruct->a = malloc(1000);
pMyStruct->b = malloc(1000);
pMyStruct->c = malloc(1000);

iResult = (pMyStruct->a != NULL) && (pMyStruct->b != NULL)
&& (pMyStruct->c != NULL);

if (iResult == 0)
{
Release(pMyStruct);
}

}

return iResult;

};

No gotos, one single return but potentially useless malloc’s. There is no
perfect solution but I prefer to do as shown above, unless the allocation of
b is dependent on the allocation of a (mapping for example).

In C++ it’s much better since you do:

MyStruct s;

// code

return;// resources get freed on return

If you don’t want to waste the stack

auto_ptr pS;

// code

return; // idem

The first language I learnt is BASIC on an Amstrad CPC 6128. I can tell you
it taught me to hate gotos.



EA

> -----Original Message-----
> From: xxxxx@lists.osr.com [mailto:bounce-287250-
> xxxxx@lists.osr.com] On Behalf Of Michal Vodicka
> Sent: vendredi 18 mai 2007 22:49
> To: Windows System Software Devs Interest List
> Subject: RE: [ntdev] RES: Strange problem with VC++ compiler because of
> goto
>
> My approach is very similar except of multiple returns. Why to
> unnecessarily repeat the same code?
>
> BOOLEAN Initialize(MyStruct *pMyStruct) {
> BOOLEAN InitReady = FALSE;
>
> > if (pMyStruct != NULL) {
> > memset(pMyStruct, 0, sizeof(MyStruct));
> >
> > if ((pMyStruct->a = malloc(1000)) == NULL) {
> goto Done;
> > }
> > if ((pMyStruct->b = malloc(1000)) == NULL) {
> > goto Done;
> > }
> > if ((pMyStruct->c = malloc(1000)) == NULL) {
> goto Done;
> > }
> InitReady = TRUE;
> > }
> Done:
> if (!InitReady) {
> Release(pMyStruct);
> }
> > return(InitReady);
> > }
> >
> This is generic approach not related to allocations only. In such a
> simple case I’d use more structured form of goto:
>
> BOOLEAN Initialize(MyStruct *pMyStruct) {
> BOOLEAN InitReady = FALSE;
>
> do {
> > if (pMyStruct == NULL) {
> break;
> }
> > memset(pMyStruct, 0, sizeof(MyStruct));
> >
> > if ((pMyStruct->a = malloc(1000)) == NULL) {
> break;
> > }
> > if ((pMyStruct->b = malloc(1000)) == NULL) {
> > break;
> > }
> > if ((pMyStruct->c = malloc(1000)) == NULL) {
> break;
> > }
> InitReady = TRUE;
> > } while (FALSE);
> >
> if (!InitReady) {
> Release(pMyStruct);
> }
> > return(InitReady);
> > }
> >
> Best regards,
>
> Michal Vodicka
> UPEK, Inc.
> [xxxxx@upek.com, http://www.upek.com]
>
>
> > ----------
> > From: xxxxx@lists.osr.com[SMTP:bounce-287247-
> xxxxx@lists.osr.com] on behalf of Edouard A.[SMTP:xxxxx@fausse.info]
> > Reply To: Windows System Software Devs Interest List
> > Sent: Friday, May 18, 2007 10:15 PM
> > To: Windows System Software Devs Interest List
> > Subject: RE: [ntdev] RES: Strange problem with VC++ compiler because
> of goto
> >
> > If I have to do pure C (fortunately this is rare… :p), I like to do
> it
> > this way:
> >
> > #include <malloc.h>
> > #include <memory.h>
> >
> > struct _MyStruct
> > {
> >
> > void *a;
> > void *b;
> > void *c;
> >
> > };
> >
> > typedef struct _MyStruct MyStruct;
> >
> > int Initialize(MyStruct *pMyStruct);
> > void Release(MyStruct *pMyStruct);
> >
> > int Initialize(MyStruct *pMyStruct)
> > {
> >
> > if (pMyStruct != 0)
> > {
> >
> > memset(pMyStruct, 0, sizeof(MyStruct));
> >
> > pMyStruct->a = malloc(1000);
> > if (!pMyStruct->a)
> > {
> > Release(pMyStruct);
> > return 0;
> > }
> >
> > pMyStruct->b = malloc(1000);
> > if (!pMyStruct->b)
> > {
> > Release(pMyStruct);
> > return 0;
> > }
> >
> > pMyStruct->c = malloc(1000);
> > if (!pMyStruct->c)
> > {
> > Release(pMyStruct);
> > return 0;
> > }
> > }
> >
> > return 1;
> >
> > };
> >
> > void Release(MyStruct *pMyStruct)
> > {
> > if (pMyStruct)
> > {
> > if (pMyStruct->a != 0)
> > {
> > free(pMyStruct->a);
> > }
> >
> > if (pMyStruct->b != 0)
> > {
> > free(pMyStruct->b);
> > }
> >
> > if (pMyStruct->c != 0)
> > {
> > free(pMyStruct->c);
> > }
> >
> > memset(pMyStruct, 0, sizeof(MyStruct));
> >
> > }
> > };
> >
> > int main(int argc, char **argv)
> > {
> >
> > MyStruct s;
> >
> > Initialize(&s);
> >
> > Release(&s);
> >
> > }
> >
> > I always encapsulate my resources allocations inside a structure, if
> I need
> > to add more I only need to modify two functions. You can of course
> factor
> > further since we have here several malloc(1000) which should in fact
> emanate
> > from another Initialize.
> >
> > I have no goto, but I have several returns. In this case however it
> is hard
> > to miss the “release” before return because there is only one call to
> > release all. I try very hard to have functions as small as possible,
> big
> > functions => more bugs. This increases the number of functions and
> the
> > initial amount of work but, to my experience, reduces the amount of
> bugs.
> >
> > The code has to respect some sort of symmetry and harmony. When your
> code is
> > symmetric and harmonic, your brain is going to repeat intuitively the
> > patterns it sees and this reduces the occurrence of bugs.
> >
> > When you start to get
> >
> > while(1)
> > {
> > if (blah)
> > {
> > If ()
> > {
> > Break;
> > }
> > Else
> > {
> > }
> > }
> > else
> > {
> > if ((p = malloc(1000)) != 0)
> > {
> > Return;
> > }
> > else
> > {
> > Continue;
> > }
> > Break;
> > }
> > }
> >
> > You WILL have memory leaks and you WILL have bugs. It’s not a problem
> of
> > break, continue, return whatever unholy keyword it’s a problem of
> structure,
> > symmetry and harmony.
> >
> > –
> >
> > Edouard A.
> >
> >
> > > -----Original Message-----
> > > From: xxxxx@lists.osr.com [mailto:bounce-287215-
> > > xxxxx@lists.osr.com] On Behalf Of Michal Vodicka
> > > Sent: vendredi 18 mai 2007 19:27
> > > To: Windows System Software Devs Interest List
> > > Subject: RE: [ntdev] RES: Strange problem with VC++ compiler
> because of
> > > goto
> > >
> > > We use similar approach and the rule is simpler: one return per
> > > function. It naturally leads to what you describe. I expected hard
> > > discussion but surprisingly, coworkers agreed with no problem.
> Probably
> > > because everybody of them already encountered a problem with
> overlooked
> > > return. Other reason is we use traces which print function name +
> > > parameters on entry and return value on leave. The label before
> leave
> > > trace is then natural.
> > >
> > > Personally, I take returns in the middle of the function as an
> evil. It
> > > becomes apparent when somebody embeds return in the macro.
> Something
> > > like this:
> > >
> > > #define CATCH_ERROR(Function) if (!Function) return
> > >
> > > Best regards,
> > >
> > > Michal Vodicka
> > > UPEK, Inc.
> > > [xxxxx@upek.com, http://www.upek.com]
> > >
> > >
> > > > ----------
> > > > From: xxxxx@lists.osr.com[SMTP:bounce-287149-
> > > xxxxx@lists.osr.com] on behalf of
> > > xxxxx@ixos.de[SMTP:xxxxx@ixos.de]
> > > > Reply To: Windows System Software Devs Interest List
> > > > Sent: Friday, May 18, 2007 9:04 AM
> > > > To: Windows System Software Devs Interest List
> > > > Subject: RE:[ntdev] RES: Strange problem with VC++ compiler
> because
> > > of goto
> > > >
> > > > hi,
> > > >
> > > > the problem with multiple returns in a function (especially in
> larger
> > > ones) is often, that some resources which are acquired (most often
> > > later during a change of the code) in that function are not freed
> at
> > > exit of the function because of an early “return”.
> > > >
> > > > Therefore - after hard discussions - we have the rule in our
> larger
> > > projects that each larger function has to have a label - most often
> > > named "exitFunction: " or so - near the end of the function. And
> > > everybody has to use “goto exitFunction” to leave the function.
> After
> > > that label all resources must be freed. Of course you have to keep
> > > track there which resources are really acquired when you reach this
> > > part of the code.
> > > >
> > > > And I think that it is completely structured code although there
> are
> > > those “gotos” inside the code. We have this discussion about gotos
> > > again and again, but I discuss about coding guidelines since more
> than
> > > 35 years now. It is very hard for my colleagues to argue with me
> about
> > > that point :wink:
> > > >
> > > > – Reinhard
> > > >
> > > >
> > > > —
> > > > Questions? First check the Kernel Driver FAQ at
> > > http://www.osronline.com/article.cfm?id=256
> > > >
> > > > To unsubscribe, visit the List Server section of OSR Online at
> > > http://www.osronline.com/page.cfm?name=ListServer
> > > >
> > >
> > > —
> > > Questions? First check the Kernel Driver FAQ at
> > > http://www.osronline.com/article.cfm?id=256
> > >
> > > To unsubscribe, visit the List Server section of OSR Online at
> > > http://www.osronline.com/page.cfm?name=ListServer
> >
> >
> > —
> > Questions? First check the Kernel Driver FAQ at
> http://www.osronline.com/article.cfm?id=256
> >
> > To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer
> >
>
> —
> Questions? First check the Kernel Driver FAQ at
> http://www.osronline.com/article.cfm?id=256
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer</memory.h></malloc.h>

Hello,

Paul Gardiner wrote:

I know one context where use of goto does seem to give more
easily maintained code. This is when freeing allocated
resources under error conditions in the absence of
exception handling.
[…]
Here is the prettier version:

{
A *a = NULL;
B *b = NULL;
C *c = NULL;
D *c = NULL;

a = AllocateA();
if(a == NULL)
return FAILED;

HERE, you have an awfull un-symmetry. What if someone adds an
“AllocateBeforeA()” *before* this line? you might forget about changing
the return to “goto”.

b = AllocateB();
if(b == NULL)
goto failure;

c = AllocateC();
if(c == NULL)
goto failure;

d = AllocateD();
if(d == NULL)
goto failure;

return SUCCESS;

failure:
FreeA(a);
FreeB(b);
FreeC(c);
return FAILED;
}

I like the following version much more:

do
{
TYPE-OF-RETURN-VALUE retValue = FAILED;

A *a = NULL;
B *b = NULL;
C *c = NULL;
D *c = NULL;

a = AllocateA();
if(a == NULL)
break;

b = AllocateB();
if(b == NULL)
break;

c = AllocateC();
if(c == NULL)
break;

d = AllocateD();
if(d == NULL)
break;

returnValue = SUCCESS;

] while(0);

if (returnValue != SUCCESS)
{
FreeA(a);
FreeB(b);
FreeC(c);
}
return returnValue;

This way, you have one return statement at the end of the function, no
“uncontrolled” goto (a break is a special kind of goto, but it is much
more controllable).

The only thing you have to care about is that the “break” cannot be used
in a loop which itself is inside of the do { … } while (0).

(I am not commenting on if I would use { } after the if; in the DDK
world, I would prefer to do so, as many functions are implemented as
“non-safe” macros, that is, which might expand to more than one
statement.)

Regards,
Spiro.


Spiro R. Trikaliotis http://opencbm.sf.net/
http://www.trikaliotis.net/ http://www.viceteam.org/

Spiro Trikaliotis wrote:

HERE, you have an awfull un-symmetry. What if someone adds an
“AllocateBeforeA()” *before* this line? you might forget about changing
the return to “goto”.

Yeah, I have to agree. Its better not to make the
first a special case, but that’s sort of orthogonal
to the issue of whether goto is sometimes useful.

When squinting at the construct:

do {
if (a)
{
break;
}
if (b)
{
break;
}
.
.
.
} while(0);

It seems to look identical to:
{
if (a)
{
goto Done;
}
if (b)
{
goto Done;
}
.
.
.
}
Done:

And in an odd twist of fate the compiler actually hates the ‘more
structured’ while(0) construct and seems to be very happy about ‘goto’.

As the while(0) form of this is unappealing to the compiler I use macrofied
TRY FINALLY LEAVE constructs to hide my use of gotos, avoid the compiler
unpleasantness, and achieve the elegance of single entry single exit code
blocks. The mindless abolition of gotos was not a stellar moment in the
history of software engineering.

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:bounce-287302-
xxxxx@lists.osr.com] On Behalf Of Paul Gardiner
Sent: Saturday, May 19, 2007 7:10 AM
To: Windows System Software Devs Interest List
Subject: Re: [ntdev] Strange problem with VC++ compiler because of goto

Spiro Trikaliotis wrote:
> HERE, you have an awfull un-symmetry. What if someone adds an
> “AllocateBeforeA()” *before* this line? you might forget about
changing
> the return to “goto”.

Yeah, I have to agree. Its better not to make the
first a special case, but that’s sort of orthogonal
to the issue of whether goto is sometimes useful.


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

Hello Mark,

Mark Roddy wrote:

When squinting at the construct:

do {
[…]
} while(0);

It seems to look identical to:
{
if (a)
{
goto Done;
}
[…]
}
Done:

Well, essentially, it is identical.

Nevertheless, I see one advantage of the construct do { … } while (0)
over the version with goto: With goto, I have seen people starting to
add more and more goto targets into the code, “as there already is a
goto, thus, it cannot be bad”. This way, the structure is lost again.

With the do while (0), it is unlikely that this will happen, as one has
to add much more to make this work.

Thus, I still prefer the do {…} while (0) construct.

And in an odd twist of fate the compiler actually hates the ‘more
structured’ while(0) construct and seems to be very happy about ‘goto’.

Well, this is bad. To be honest, I never analysed what the compiler
generates out of this.

Of course, there was never much need for Microsoft to think about the do
while (0) construct. In many other sources (for gcc, for example), you
find that construct rather often in C macros in order to make it
“if-safe”:

#define DO_SOMETHING() do { do_something1(); do_something2(); } while (0)

and then

if ()
DO_SOMETHING();

without needing to add the braces around DO_SOMETHING().

> As the while(0) form of this is unappealing to the compiler I use
> macrofied TRY FINALLY LEAVE constructs to hide my use of gotos, avoid
> the compiler unpleasantness, and achieve the elegance of single entry
> single exit code blocks.

Well, yes, this is another approach. It might even prevent the problem I
wrote about above, that people start adding more and more labels into
the code.

Nevertheless, I do not like to “redefine” the language. Essentially,
this is what you are doing. But I must admit, in this special case, this
seems to be a good trade-off between efficiency and
readability/maintainability.

> The mindless abolition of gotos was not a stellar moment in the
> history of software engineering.

Gotos are not being abolited (?) completely. It is just mindless
unstructured gotos which have been banned (IMHO). Every break is nothing
else than some (structured) form of goto - so, if gotos would have to
go, a break would not be possible, either. :wink:

Regards,
Spiro.


Spiro R. Trikaliotis http://opencbm.sf.net/
http://www.trikaliotis.net/ http://www.viceteam.org/