An error occurs when a function result is dereferenced if used as another function's argument: void *func(int num) { static int val; val=num; return (void*)&val; } int main() { printf("%d %d %d\n", *((int*)func(1)), *((int*)func(2)), *((int*)func(3))); return 0; } Output is "1 1 1" instead of "1 2 3". Compiled using "gcc test.c -o test".
It is undefined on which function call is done in what order and also were the dereferencing is done, before or after the next function call. *** This bug has been marked as a duplicate of 11751 ***
> It is undefined on which function call is done in what order It does not matter in this example. > and also were the > dereferencing is done, before or after the next function call. It does not matter either. The evaluation of a function argument is an atomic procedure. If it starts it should generate a result. Isn't it strange if the compiler evaluates a little bit of the first argument, then a little bit of the second argument, then a little bit of the third argument, then goes back to the first and completes the evaluation?
(In reply to comment #2) > > It is undefined on which function call is done in what order > > It does not matter in this example. > Why do you think that? It does generate a call to func but not as you expected it. Anyways the way GCC is compiling your code is the following which is valid under the standard: int *a, *b, *c; c = func(3); b = func(2); a = func(1); printf("%d %d %d\n", *(a), *(b), *(c)); so the order is still undefined as there is no sequence point between the function calls. *** This bug has been marked as a duplicate of 11751 ***
(In reply to comment #2) > It does not matter either. The evaluation of a function argument is an atomic > procedure. If it starts it should generate a result. Isn't it strange if the > compiler evaluates a little bit of the first argument, then a little bit of the > second argument, then a little bit of the third argument, then goes back to the > first and completes the evaluation? Why do you think it is an atomic procedure? There is nothing in the standard that says: f(a, a++, b+(a++)+(a++)) evaluates each of those as atomic in fact the reverse is true in that it says the order is undefined as there is no sequence point inbetween those arguments as the comma in this case is not the comma operator but argument seperator.
> > > It is undefined on which function call is done in what order > > It does not matter in this example. > Why do you think that? Because the result is "x x x" for all orders instead of 1 2 3. > int *a, *b, *c; > c = func(3); > b = func(2); > a = func(1); > > printf("%d %d %d\n", *(a), *(b), *(c)); I understand and disagree that this is not a bug. Consider the following example: char *arr; void read_input() { arr=malloc(10); read(fd, arr, 10); } void print_input() { if (!arr) printf ("input empty\n"); else { printf("%s\n", arr); free(arr); arr=NULL; } } go(read_input, print_input); If the compiler "optimizes" go() call so that the first argument is not evaluated completely then evaluates the second argument and finally completes evaluation of the first argument after arr was freed, then it is a segfault. However, the function is evaluated correctly if the arguments are evaluated completely.
In C, there is no ordering left to right, please go read the C FAQ at: http://www.eskimo.com/~scs/c-faq.com/expr/index.html subpage: http://www.eskimo.com/~scs/c-faq.com/expr/comma.html This page answers your question of this being undefined and this is not a bug in GCC. *** This bug has been marked as a duplicate of 11751 ***
(In reply to comment #6) > In C, there is no ordering left to right, please go read the C FAQ at: > http://www.eskimo.com/~scs/c-faq.com/expr/index.html > subpage: > http://www.eskimo.com/~scs/c-faq.com/expr/comma.html The problem has nothing to do with ordering. It is in because arguments are evaluated not completely before the next one is evaluated.
(In reply to comment #7) > (In reply to comment #6) > > In C, there is no ordering left to right, please go read the C FAQ at: > > http://www.eskimo.com/~scs/c-faq.com/expr/index.html > > subpage: > > http://www.eskimo.com/~scs/c-faq.com/expr/comma.html > The problem has nothing to do with ordering. It is in because arguments are > evaluated not completely before the next one is evaluated. Even then, the order inside the epxressions is not specified which means a+b+c+d can be such that the a, b, c, and d subexpressions are in any order as long as there are not squence points, even then it is only the a partial ordering. For an example: (a, b) + (c, d) + (e, f) can be evaulated in the following order and would be still be valid: a c e b d f add add or a b c e d f add add as long as the ordering of a comes before b and c comes before d and e comes before f, it is valid. This is what is meant by partial ordering. therefor in your orginal expample we have: f ("", OP0(f0()), OP1(f1()), OP2(f2())); the ordering here of each sub expression is not specified in that f0() might come before f2() but it does have to come before the call to f and the operation OP0 just because of dependicies. Hopefully this explains what is going on here and why this bug is invalid and is a dup of PR 11751. What you need to think of is that the comma in a function call is just a seperator and there is no evaulation requirement on which expression (or subexpression) gets evaulated first in the same way: (a++ + b++) + (a++ + b++); there is no requirment which a++ (or b++) is evaulated first.
> It does not matter either. The evaluation of a function argument is an atomic > procedure. No, it actually isn't. > If it starts it should generate a result. Isn't it strange if the > compiler evaluates a little bit of the first argument, then a little bit of the > second argument, then a little bit of the third argument, then goes back to the > first and completes the evaluation? Maybe. But it's allowed under the standard, and if the compiler can produce better code this way it should use its liberty. W.
Uhm, this has nothing to do at all with evaluation order. Evaluation order of arguments is unspecified (not undefined, which wouldn't make a lot of sense), but that is in fact irrelevant here, it could lead to, say, 3 1 2, but not 1 1 1. The actual problem is that val is modified more than once without an intervening sequence point, which makes the behavior undefined.
Subject: Re: function result is dereferenced error On Tue, 18 Apr 2006, falk at debian dot org wrote: > Uhm, this has nothing to do at all with evaluation order. Evaluation > order of arguments is unspecified (not undefined, which wouldn't make a > lot of sense), but that is in fact irrelevant here, it could lead to, > say, 3 1 2, but not 1 1 1. > > The actual problem is that val is modified more than once without an > intervening sequence point, which makes the behavior undefined. No, this testcase is unspecified, not undefined. There are intervening sequence points at the start and end of each call to function, and function calls do not overlap (DR#087); each call to func suspends the execution of main until func returns. However, the evaluation of the arguments to printf may overlap and the order is unspecified, so there are many possible outputs from the program (but "3 2 1" and "3 1 1", for example, are not possible).
(In reply to comment #11) > No, this testcase is unspecified, not undefined. There are intervening > sequence points at the start and end of each call to function OK. > However, the evaluation of the > arguments to printf may overlap and the order is unspecified, so there are > many possible outputs from the program (but "3 2 1" and "3 1 1", for > example, are not possible). I don't understand why is "3 2 1" is not possible. How about "1 1 1"? Is this a bug in gcc after all?
Subject: Re: function result is dereferenced error On Tue, 18 Apr 2006, falk at debian dot org wrote: > > However, the evaluation of the > > arguments to printf may overlap and the order is unspecified, so there are > > many possible outputs from the program (but "3 2 1" and "3 1 1", for > > example, are not possible). > > I don't understand why is "3 2 1" is not possible. How about "1 1 1"? Is > this a bug in gcc after all? "1 1 1" is possible: first evaluate func(3), then func(2), then func(1), then do all the dereferences. To get "3 2 1", the initial "3" requires func(3) to be evaluated between the evaluation of func(1) and its dereference, so func(3) is evaluated after func(1); but likewise the final "1" requires func(1) to be evaluated after func(3).