Does this invoke undefined behavior?

D

David Resnick

I had a problem going from gcc 2.96 to gcc 3.2.3 and narrowed it down to
the following code. The question is whether the problem is undefined
behavior on the code's part or a compiler bug.

#include <stdlib.h>
#include <stdio.h>

struct frob {
char a;
int b;
};

static struct frob *test;

int frobit(void)
{
const char *move_things = malloc(10*sizeof(struct frob));
struct frob *tmp = realloc(test, 1000*sizeof(struct frob));

move_things = move_things;
if (tmp == NULL) {
fprintf(stderr, "realloc of test failed\n");
exit(1);
}

test = tmp;
return 11;
}

int main(void)
{
int i;

test = malloc(10 * sizeof(struct frob));
if (test == NULL) {
fprintf(stderr, "malloc of test failed\n");
exit(1);
}

for (i = 0; i < 10; i++) {
test.b = i;
}

i = 0;
printf("test[0]->b = %d\n", test[0].b);
test.b = frobit();
printf("test[0]->b = %d\n", test[0].b);
return 0;
}

OK, what is the problem? In gcc 2.96 the location of test.b in the
assignment was figured out after the frobit function returned. In gcc
3.2.3 it is figured out before the frobit function returns. And
the realloc within frobit() moves it.

I've tried figure out in the standard whether the LHS in the assignment
needs to be evaluated before/after the RHS or if that is undefined, but
I can't seem to find that. I see in the FAQ stuff like section 3.1,
does that apply here? Any pointer to the relevant standard section
appreciated.

Yes, yes, statics are evil. Usually. I know, not really relevant here,
not going to change in this case.

Thanks,

-David
 
D

Dan Pop

In said:
I had a problem going from gcc 2.96 to gcc 3.2.3 and narrowed it down to
the following code. The question is whether the problem is undefined
behavior on the code's part or a compiler bug.

Undefined behaviour, of course.
OK, what is the problem? In gcc 2.96 the location of test.b in the
assignment was figured out after the frobit function returned. In gcc
3.2.3 it is figured out before the frobit function returns. And
the realloc within frobit() moves it.

I've tried figure out in the standard whether the LHS in the assignment
needs to be evaluated before/after the RHS or if that is undefined, but
I can't seem to find that.


You won't find it, it's covered by the more general statement that the
order of evaluation of an expression is *unspecified*. If a certain
evaluation order renders the behaviour of your code undefined, your code
is considered as invoking undefined behaviour. And, since your realloc
call can move the resized memory block, all pointers inside the original
block have indeterminate values when realloc returns. By the wording of
C99 they have indeterminate values even if the block is NOT moved by
realloc:

The value of a pointer becomes indeterminate when
the object it points to reaches the end of its lifetime.
....
2 The realloc function deallocates the old object pointed to by
^^^^^^^^^^^^^^^^^^^^^^^^^^
ptr and returns a pointer to a new object that has the size
^^^^^^^^^^^^^^^
specified by size.
Yes, yes, statics are evil. Usually. I know, not really relevant here,
not going to change in this case.

Your code is broken and it's entirely up to you to decide how to fix it.

Dan
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top