Fantastic exchange from DConf
Ali Çehreli via Digitalmars-d
digitalmars-d at puremagic.com
Wed May 10 04:38:48 PDT 2017
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->data1, bufsz);
>>> if (fwrite(tmp, strlen(tmp), 1, fp) != 1)
>>> {
>>> fclose(fp);
>>> unlink("blah");
>>> return IO_ERROR;
>>> }
>>>
>>> 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. ;)
> Eventually, the idiom that I (and others) eventually converged on looks
> something like this:
>
> int myfunc(blah_t *blah, bleh_t *bleh, bluh_t *bluh) {
> void *resource1, *resource2, *resource3;
> int ret = RET_ERROR;
>
> /* Vet arguments */
> if (!blah || !bleh || !bluh)
> return ret;
>
> /* 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.
>
> /* Do actual work */
> if (do_step1(blah, resource1) == RET_ERROR)
> goto EXIT;
>
> if (do_step2(blah, resource1) == RET_ERROR)
> goto EXIT;
>
> if (do_step3(blah, resource1) == RET_ERROR)
> goto EXIT;
>
> ret = RET_OK;
> EXIT:
> /* Cleanup everything */
> if (resource3) release(resource3);
> if (resource2) release(resource2);
> if (resource1) release(resource1);
>
> return ret;
> }
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.
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.
Ali
More information about the Digitalmars-d
mailing list