Re: broken code only when optimized "-O2"

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 12/21/21 18:05, David Brown wrote:
On 21/12/2021 17:05, Stefan Ring via Gcc-help wrote:
On Tue, Dec 21, 2021 at 4:40 PM Adrian Moreno via Gcc-help
<gcc-help@xxxxxxxxxxx> wrote:

I'd really appreciate any hint or idea to try to understand this problem.

I guess the compiler doesn't like the dereferencing of uninitialized
pointers (in the sizeof expressions). I am not 100% sure that this
counts as dereferencing, but I would assume so. Because of this the
compiler will be free to behave however it likes to.


The operand of a sizeof expression is not evaluated (unless it is a
VLA).  So there is no problem with the "member1 = malloc(sizeof
*member1);" lines.  (Which is fortunate, because it is a very common idiom!)

I think the next step would be to start pulling in some of the
definitions for the various macros here, and then trying to reduce the
code further to get a smaller test case.


Yes, that's the road I'm taking. Thanks for the suggestion.

One of the things that originally felt smelly was that the fact that the macros that iterate the list elements assume the "struct ovs_list" element is embedded into another "struct member":

struct member *pos = 0;

for ((((pos) = ((struct member *) (void *) ((uintptr_t)(void *)((&start)->next) - __builtin_offsetof (struct member, elem)))));
     &(pos)->elem != (&start);
((pos) = ((struct member *) (void *) ((uintptr_t)(void *)((pos)->elem.next) - __builtin_offsetof (struct member , elem)
)))) {
   [... use pos ]

however, the beginning of the list is a "struct ovs_list" defined in the stack and not embedded into a "struct member".

Therefore, "(&start)->next - __builtin_offsetof (struct member, elem)" actually points to somewhere in the stack that contains who knows what. (Note: initially start->next = start)

In fact, if I make the struct offsets zero:

struct member {
    struct ovs_list elem;
    [ ... ]
    int order;
};

... the code works. However if I use:

struct member {
    int padding[10];
    struct ovs_list elem;
    [ ... ]
    int order;
};

... the code fails.

Does anything of what I'm saying make sense so far?

If the code inside the loop just made use of "pos" through "(&pos->elem)" then the compiler could(?) be ok with it but the loop actually contains:
           if (member->order > pos->order) {
               break;
           }

So here I do not know what the compiler would think about "pos" if it happens to point to some invalid stack address.

Thanks for the help.

--
Adrián Moreno




[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux