Fantastic exchange from DConf

H. S. Teoh via Digitalmars-d digitalmars-d at puremagic.com
Wed May 10 10:51:38 PDT 2017


On Wed, May 10, 2017 at 04:38:48AM -0700, Ali Çehreli via Digitalmars-d wrote:
> On 05/09/2017 10:26 PM, H. S. Teoh via Digitalmars-d wrote:
> > On Wed, May 10, 2017 at 01:32:33AM +0000, Jack Stouffer via Digitalmars-d
> wrote:
> >> On Wednesday, 10 May 2017 at 00:30:42 UTC, H. S. Teoh wrote:
[...]
> >>> 		strncpy(tmp, desc->data2, bufsz);
> >>> 		if (fwrite(tmp, strlen(tmp), 1, fp) != 1)
> >>> 		{
> >>> 			fclose(fp);
> >>> 			unlink("blah");
> >>> 			return IO_ERROR;
> >>> 		}
> >>
> >> I think you cause a memory leak in these branches because you
> >> forget to free tmp before returning.
> >
> > Well, there ya go. Case in point.
> 
> I caught that too but I thought you were testing whether we were
> listening.  ;)

Haha, I guess I'm not as good of a C coder as I'd like to think I am.
:-D


[...]
> > 		/* Acquire resources */
> > 		resource1 = acquire_resource(blah->blah);
> > 		if (!resource1) goto EXIT;
> >
> > 		resource2 = acquire_resource(bleh->bleh);
> > 		if (!resource1) goto EXIT;
> 
> Copy paste error! :p (resource1 should be resource2.)
> 
> >
> > 		resource3 = acquire_resource(bluh->bluh);
> > 		if (!resource1) goto EXIT;
> 
> Ditto.

Ouch.  Ouch.  :-D

But then again, I've actually seen similar copy-paste errors in real
code before, too. Sometimes they could be overlooked for >5 years (I kid
you not, I actually checked the date in svn blame / svn log).


[...]
> As an improvement, consider hiding the checks and the goto statements
> in macros:
> 
>     resource2 = acquire_resource(bleh->bleh);
>     exit_if_null(resource1);
> 
>     err = do_step2(blah, resource1);
>     exit_if_error(err);
> 
> Or something similar... Obviously, it requires certain standardization
> like functions never having a goto statement, yet all having an EXIT
> area, etc.  It makes C code very uniform, which is a good thing as you
> notice nonstandard idioms quickly.

Yes, eventually this is the only sane and consistent way to deal with
these problems.  Unfortunately, in C this can only be done by
convention, which means that some non-conforming code will inevitably
slip through and cause havoc.

Also, this starts running dangerously near the slippery slope down into
macro hell, where the project accretes its own idiomatic set of
inscrutable macro usage conventions and eventually almost all of the C
syntax has disappeared and the code no longer looks like C.  Then along
comes New Recruit, and he makes a right mess with it because he doesn't
understand the 15-level-deep nested macros in the global
include/macros.h file that's become a 5200-line monstrosity of
unreadable CPP hacks.  (Also not exaggerating: the very project I'm
working on has a module that's written this way, and only the initiated
dare dream of fixing bugs in those macros. Fortunately, they have not
yet nested to 15 levels deep, so for the most part you just copy and
paste existing working code and pray that it will Just Work by analogy.
Actually understand what you just wrote? Pfeh! You don't have time for
that. The customer wants the release by last week. Copy-n-paste cargo
cult FTW!)


> This safer way of needing to do everything in steps of two lines is
> one of the reasons why I was convinced that exceptions are superior to
> return codes.
[...]

Yeah, once practically every single statement in your function is an
if-statement checking for error codes, you start wondering, why can't
the language abstract this nasty boilerplate away for me?! And then the
need for exceptions becomes clear.


T

-- 
Written on the window of a clothing store: No shirt, no shoes, no service.


More information about the Digitalmars-d mailing list