[PATCH] memset 0 in obscure is optimized away by compiler

Cathey, Jim jcathey at ciena.com
Wed Apr 16 18:01:38 UTC 2014


Generally C compilers assume that an address
passed to a function (free(p)) _might_ be dereferenced,
and so would not optimize away the memset(p,...)

If a particular C compiler thinks it knows what
free() is, and that it doesn't dereference its argument,
then it might think it was justified in doing this.

That's a broken C compiler if you ask me, unless
you _can_ tell it not to make assumptions about what
particularly-named functions do.  (Else cross-compiling,
or developing in/for peculiar environments is impossible.)

A C compiler that _knows_ free() doesn't dereference its
argument _is_ entirely justified in eliminating the
memset.  The tool to tell the C compiler that there
are other factors operating behind the C compiler's
back is "volatile", which basically tells it "you don't
know everything here, so stop screwing around and do exactly
what I say."  It's an overlarge hammer in this case, though.

-- Jim

-----Original Message-----
From: busybox-bounces at busybox.net [mailto:busybox-bounces at busybox.net] On Behalf Of Denys Vlasenko
Sent: Wednesday, April 16, 2014 10:52 AM
To: Tito
Cc: busybox
Subject: Re: [PATCH] memset 0 in obscure is optimized away by compiler

On Wed, Apr 16, 2014 at 6:47 PM, Tito <farmatito at tiscali.it> wrote:
> Hi,
> while reading some interesting stuff about memset being optimized
> away by compilers if the variable is not read after the memset call
> I recalled there was something similar in libbb/obscure.c file:
>
> static int string_checker(const char *p1, const char *p2)
> {
>         int size, i;
>         /* check string */
>         int ret = string_checker_helper(p1, p2);
>         /* make our own copy */
>         char *p = xstrdup(p1);
>
>         /* reverse string */
>         i = size = strlen(p1);
>         while (--i >= 0) {
>                 *p++ = p1[i];
>         }
>         p -= size; /* restore pointer */
>
>         /* check reversed string */
>         ret |= string_checker_helper(p, p2);
>
>         /* clean up */
>         memset(p, 0, size);
>
>         free(p);
>
>         return ret;
> }

$ make libbb/obscure.s

and I see the memset (inlined by compiler):

        cld
        xorl    %eax, %eax      # tmp76
        movl    %ebx, %edi      # p.101,
        movl    %esi, %ecx      # D.7349, D.7349
        rep
        stosb

Perhaps because compiler doesn't know that free(p) doesn't use
the contents of *p.

>
> -       /* clean up */
> -       memset(p, 0, size);
> +       /* clean up, don't use memset as it is optimized away by compiler */
> +       /*memset(p, 0, size);*/
> +       nuke_str(p);
>         free(p);

This may be unnecessary wrt correctness (memset isn't eliminated),
but it is also _fewer bytes of code_!

Applied to git, thanks!
_______________________________________________
busybox mailing list
busybox at busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


More information about the busybox mailing list