Re: large files: when ubiquitous?

From: Kasper Dupont (kasperd_at_daimi.au.dk)
Date: 05/09/04


Date: Sun, 09 May 2004 10:56:58 +0200


"P.T. Breuer" wrote:
>
> It doesn't help. I was merely pointing out that the compiler cannot
> calculate what does or does not access a given memory area, therefore
> it should NEVER make optimizations that assume that it has unique
> access to a given memory area. You supplied a subtle example.

Wrong.

>
> > If you don't do so, the
> > compiler will make optimizations giving unexpected
> > behaviour. That have been seen so often.
>
> Then it's a bug. Optimizations should should not change program
> semantics for programs that are within language spec.

The program is outside specs.

> You gave a
> program which had a well defined result,

No, it had an udefined result.

> the compiler should not change
> that result. In your case the compiler changed
>
> *a = 1
> *b = 2
> return *a
>
> to *b = 2
> return *a = 1

I don't think that is what happened. I think it
changed the code to:

*a=42;
*b=3.14;
return 42;

which is correct.

>
> But it should not change the behaviour of a non-broken program.
> And you gave an example where it did. Bug.

No, I gave an example of a program with undefined
behavior. If you still think this is a compiler
bug, *you* report it on http://gcc.gnu.org/bugzilla/
and then stop bothering us about it before you have
reported it and told us the bug number.

> >
> > Yes. And the assignments will probably be done in
> > the order they appear in the code. Which means the
> > contents of the memory as the function returns
> > will be as expected.
>
> But apparently that is not what you observed.

You are wrong again. Can you without compiling this
program tell me, what it will return with and without
optimization? (I predicted the outcome correctly)

#include <stdio.h>
#include <stdlib.h>
static inline long f(long *a, float *b)
{
  *a=42;
  *b=3.14;
  return *a;
}
int main()
{
   void *p=malloc(42);
   printf("%ld\n",f(p,p));
   printf("%lf\n",*(float*)p);
   return 0;
}

>
> Sorry, I meant "semantically". It moved it before the *a=42; thus
> making its effect semantically invisible, i.e. making it disapppear,
> i.e. eliding it.

Wrong again.

>
> > > Compiler mistake if it does.
> >
> > It doesn't.
>
> It did, in the sense I meant.

Nope.

>
> > It is not a compiler bug. There is a bug in the
> > program I wrote, which I deliberately put there to
> > demonstrate my point.
>
> There is no bug in your subroutine.

Correct, there is only a bug in the arguments given by
main when the function is called.

> It has a defined result.

Which includes returning 42 for any valid argument,
which it also does. When optimized it happens to
return 42 even for invalid arguments, because that is
the most efficient code gcc could come up with.

> Try
>
> int f(int *a, int *b) {
> *a = 1;
> *b = 2;
> return *a;
> }
>
> and call it with
>
> int i;
> f(&i,&i);

Why should I try it. No type punning is going on.
Obviously this will return 2. (If it didn't that would
be a compiler bug).

>
> > > Rewrite code for f as
> > > inline local function using parents variables, or macro.
> >
> > Why should I?
>
> So that it won't have to pass the variables concerned by reference.

The program was written to demonstrate an aspect of
type punning. If I changed it in the way you suggest,
it would no longer show what it is to show.

>
> > > As I said below, at least
> > > void* is a contractural promise that it's 4-aligned.
> >
> > No.
>
> Yes.

#include <stdio.h>
#include <stdlib.h>
void test(void *a, void *b)
{
  printf("%p %p\n",a,b);
}
int main()
{
   void *p=malloc(42);
   void *v=(void*)(((char*)p)+1);
   test(p,v);
   return 0;
}
>
> > malloc guarantee the returned memory will satisfy
> > the alignment requirement of any type.
>
> Which is at least 4-aligned. And I have "types" which "require" to
> be aligned at 4096, like "pages", come to that. Try writing to a
> raw device from something that isn't! But of course I know what you
> mean .. you don't mean to include types like
>
> struct page {
> char start[0] __aligned__(4096);
> }
>
> (yeah, sorry if my syntax is off - I'm not going to look up how to
> align), but instead you mean int, long, void * and so on ...

Alignment is a gcc extension and as such doesn't have
to conform with any standard. Some alignment requests
are impossible to satisify and are silently ignored.
Try this program:

#include <stdio.h>
#include <stdlib.h>
struct page {
  char start[0] __attribute__((aligned(4096)));
};
struct page test1;
int main()
{
  struct page test2;
  printf("%p %p\n",&test1,&test2);
  return 0;
}

Of course it would be nice if gcc produced a warning
in such cases. It think it took me an hour the first
time I made that mistake to realize why it wouldn't
work.

>
> > > Making promises is
> > > a good thing, in general, imo.
> > >
> > > If we pass char* instead to f,
> >
> > What exactly did you have in mind? Casting the pointer
>
> Would you mind not _arguing_ about everything from here to kingdom
> come? I fail to see the point in it!

You were the one to make a statement with no obvious
point, I just want to know what you are thinking.

>
> > to a char pointer type or changing p to be a char
> > pointer would result in a warning about incompatible
> > pointer types.
>
> I really am not sure what you mean. There is no such thing as
> "incompatible pointer types" in general semantic terms (this is C!),

Then why do I get this warning all the time?

test.c: In function `main':
test.c:13: warning: passing arg 1 of `fprintf' from incompatible pointer type
test.c:13: warning: passing arg 2 of `fprintf' from incompatible pointer type

>
> > That is completely unrelated to
> > alignment, and would happen even if both types had
> > the same size and the same alignment requirement. And
> > the code would behave exactly the same.
>
> But you said the code behaved differently according to how you
> optimized it! So what "same" do you mean?

It behave the same with a char pointer and with a void
pointer. And in both cases the program will produce
different results with and without optimization.

>
> > > So do you think the compiler will warn you about type punning in your
> > > example?
> >
> > The compiler doesn't warn about anything in my example.
>
> And it optimizes it wrongly?

No, the optimization is fine. The original program is
buggy. But of course it is impossible for the compiler
to warn about all buggy programs. Some bugs cannot be
detected at compile time.

>
> I know. I believe that is what I said, but perhaps I am alone in that
> belief ... I said "Wouldn't reading \"anything\" from a void* be
> safer?"

You can't read *anything* from a void*.

> And I didn't say anything about "dereferencing a void".

The only way you can read what is pointed to by a
pointer is by derferencing it. So yes, you did talk
about dereferencing a void.

>
> > same address as any variable of a significant different
> > type (except from char). Replacing char with void in the
> > description would make no sense at all, because you cannot
> > use expressions of type void for anything.
>
> Pardon me if I skip this particular piece of blue-unicorn-ness.

You obviously still don't have a clue. I give up. I'm
not able to explain type punning such that *you* will
understand.

-- 
Kasper Dupont -- der bruger for meget tid paa usenet.
For sending spam use abuse@mk.lir.dk and kasperd@mk.lir.dk
I'd rather be a hammer than a nail.


Relevant Pages

  • Re: Strange behaviors when debugging release
    ... debugger report honest information, but only in the context of unoptimized code. ... bug only shows up in optimized code, you have to learn how to read assembly code. ... caused that bad pointer to overwrite something. ... One test of this is to turn off optimizations during release debugging. ...
    (microsoft.public.vc.mfc)
  • Re: Function prefix comments in C files
    ... now that reminds me of a bug I spent an unreasonable time searching ... It turned out that when the compiler had its ... default optimization level on the access to the pointer was ... With optimization turned off access was no longer atomic and it ...
    (comp.arch.embedded)
  • Re: /Od compiler option problem
    ... >> found out that when I had the compiler option /Od set the project would ... >> work properly but when it was not set the bug would appear. ... > When optimizations are enabled the compiler may do those things and more. ... > declare success again or you can try to find the cause. ...
    (microsoft.public.dotnet.languages.vc)
  • Re: [64-bit Delphi] A msg from Hairy (van Tassel)
    ... > TeamB members telling the poster he's got it all wrong, ... Update to D7 introduced bugs in the compiler. ... No one yet has been able to point to a bug ... optimizations, but the removal of optimizations is /not/ a bug, despite ...
    (borland.public.delphi.non-technical)
  • Re: /Od compiler option problem
    ... > work properly but when it was not set the bug would appear. ... /Od means "disable the optimizing compiler". ... It is important to disable optimizations while ... declare success again or you can try to find the cause. ...
    (microsoft.public.dotnet.languages.vc)