Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #18846 > unrolled thread

addresses of variables

Started byZero <chefmuetze@web.de>
First post2012-03-18 03:56 -0700
Last post2012-03-21 11:04 -0400
Articles 15 on this page of 35 — 13 participants

Back to article view | Back to comp.lang.c


Contents

  addresses of variables Zero <chefmuetze@web.de> - 2012-03-18 03:56 -0700
    Re: addresses of variables "BartC" <bc@freeuk.com> - 2012-03-18 11:18 +0000
    Re: addresses of variables jt@toerring.de (Jens Thoms Toerring) - 2012-03-18 11:18 +0000
    Re: addresses of variables pete <pfiland@mindspring.com> - 2012-03-18 07:30 -0500
      Re: addresses of variables Zero <chefmuetze@web.de> - 2012-03-18 04:42 -0700
        Re: addresses of variables Lowell Gilbert <lgusenet@be-well.ilk.org> - 2012-03-19 10:52 -0400
          Re: addresses of variables Stephen Sprunk <stephen@sprunk.org> - 2012-03-19 12:55 -0500
            Re: addresses of variables James Kuyper <jameskuyper@verizon.net> - 2012-03-19 14:30 -0400
              Re: addresses of variables jacob navia <jacob@spamsink.net> - 2012-03-19 20:11 +0100
                Re: addresses of variables hoganlong@gmail.com - 2012-03-19 12:17 -0700
                  Re: addresses of variables James Kuyper <jameskuyper@verizon.net> - 2012-03-19 16:15 -0400
                    Re: addresses of variables hoganlong@gmail.com - 2012-03-19 14:18 -0700
                  Re: addresses of variables "io_x" <a@b.c.invalid> - 2012-03-19 23:26 +0100
              Re: addresses of variables Stephen Sprunk <stephen@sprunk.org> - 2012-03-20 03:52 -0500
                Re: addresses of variables James Kuyper <jameskuyper@verizon.net> - 2012-03-20 06:00 -0400
                  Re: addresses of variables Stephen Sprunk <stephen@sprunk.org> - 2012-03-20 16:47 -0500
                    Re: addresses of variables James Kuyper <jameskuyper@verizon.net> - 2012-03-20 18:37 -0400
                      Re: addresses of variables Stephen Sprunk <stephen@sprunk.org> - 2012-03-21 17:58 -0500
                        Re: addresses of variables James Kuyper <jameskuyper@verizon.net> - 2012-03-21 20:24 -0400
                          Re: addresses of variables Stephen Sprunk <stephen@sprunk.org> - 2012-03-21 23:53 -0500
                            Re: addresses of variables James Kuyper <jameskuyper@verizon.net> - 2012-03-22 06:22 -0400
                              Re: addresses of variables Kenneth Brody <kenbrody@spamcop.net> - 2012-03-22 12:01 -0400
                                Re: addresses of variables Stephen Sprunk <stephen@sprunk.org> - 2012-03-24 16:09 -0500
                              Re: addresses of variables Jens Gustedt <jens.gustedt@loria.fr> - 2012-03-23 13:41 +0100
                                Re: addresses of variables James Kuyper <jameskuyper@verizon.net> - 2012-03-23 09:06 -0400
                                  Re: addresses of variables Jens Gustedt <jens.gustedt@loria.fr> - 2012-03-23 19:47 +0100
                                    Re: addresses of variables James Kuyper <jameskuyper@verizon.net> - 2012-03-23 16:04 -0400
                                      Re: addresses of variables Jens Gustedt <jens.gustedt@loria.fr> - 2012-03-24 00:19 +0100
                                        Re: addresses of variables James Kuyper <jameskuyper@verizon.net> - 2012-03-23 22:20 -0400
                                          Re: addresses of variables Jens Gustedt <jens.gustedt@loria.fr> - 2012-03-24 09:39 +0100
              Re: addresses of variables Anders Wegge Keller <wegge@wegge.dk> - 2012-03-20 20:02 +0100
                Re: addresses of variables James Kuyper <jameskuyper@verizon.net> - 2012-03-20 15:18 -0400
                  Re: addresses of variables Anders Wegge Keller <wegge@wegge.dk> - 2012-03-21 21:37 +0100
            Re: addresses of variables Lowell Gilbert <lgusenet@be-well.ilk.org> - 2012-03-20 11:52 -0400
              Re: addresses of variables Kenneth Brody <kenbrody@spamcop.net> - 2012-03-21 11:04 -0400

Page 2 of 2 — ← Prev page 1 [2]


#18940

FromJames Kuyper <jameskuyper@verizon.net>
Date2012-03-22 06:22 -0400
Message-ID<jkeuhe$3df$1@dont-email.me>
In reply to#18938
On 03/22/2012 12:53 AM, Stephen Sprunk wrote:
> On 21-Mar-12 19:24, James Kuyper wrote:
>> On 03/21/2012 06:58 PM, Stephen Sprunk wrote:
>>> On 20-Mar-12 17:37, James Kuyper wrote:
>> ...
>>>> implementation would produce such an optimization. But the key point is
>>>> that taking the address is not the right trigger - it's what happens to
>>>> that address that matters. If nothing "meaningful" happens to it, the
>>>> address doesn't have to mean anything real, and actual storage of the
>>>> value at the addressed location doesn't have to happen.
>>>
>>> If nothing "meaningful" was done with the address, then presumably other
>>> optimizations would eliminate the code that generated it, thus allowing
>>> the compiler to migrate or eliminate the variable.
>>
>> I don't follow that - why would a situation that renders it unnecessary
>> to store a variable in addressable memory imply that it's unnecessary to
>> store it anywhere?
> 
> Concrete example:
> 
> int quux(void)
> {
>   int foo = 42;
>   int *bar = &foo;
>   return foo;
> }
> 
> 1. Both foo and bar start out in memory.
> 2. foo can't be migrated to a register because of the &foo.
> 3. bar is eliminated via dead code elimination.
> 4. foo can now be migrated to a register.
> 5. No address is needed for either foo or bar.

A prime example of a situation where neither foo, nor bar, nor the
address of foo, are needed.

> OTOH, say you have this:
> 
> #include <stdio.h>
> int quux(void)
> {
>   int foo = 42;
>   int *bar = &foo;
>   printf("%p\n", (void*)bar);
>   return foo;
> }
> 
> 1. Both foo and bar start out in memory.
> 2. foo can't be migrated to a register because of the &foo.
> 3. bar is migrated to a register.
> 4. An address is needed for foo but not for bar.
> 
> Can you give a similar example for what you're describing--and your
> mental model of what a compiler would do with it?

Yes, the second case you've just given fits what I'm talking about
exactly. Having recognized that there's absolutely no need to store 42
anywhere, the compiler reserves an arbitrary address for foo, but never
bothers storing anything at that address. That address is stored in a
register and passed to printf(), and is used for no other purpose. The
compiler need only ensure that the address is not used for any other
object that might have a lifetime that overlaps the call to quux(),
which is something it would have had to do anyway, if 42 had been stored
there.

If foo had static storage duration, there would be the possibility that
some other part of the code could ask the user to give foo's address
back to it, and then dereference a pointer to foo, which would make this
no longer a valid optimization. Because foo actually has automatic
storage duration, there's no possible way to write code which is
guaranteed to use that address during foo's lifetime, not even with
multi-threaded code.

Note: I'm winging it on that last statement. I've not had time to
assimilate C's new support for multi-threaded code. If there's some way
to guarantee that a scanf() call followed by a dereference in some other
part of the program will be executed between the printf() and the return
in quux(), then I'm wrong. But I'd expect that the ability to guarantee
such sequencing would require executing a call to one of the new
thread-related functions between the printf() and the return. Code where
such sequencing is merely possible, but not guaranteed, has undefined
behavior if it doesn't execute in that sequence, thereby allowing the
optimization.
-- 
James Kuyper

[toc] | [prev] | [next] | [standalone]


#18942

FromKenneth Brody <kenbrody@spamcop.net>
Date2012-03-22 12:01 -0400
Message-ID<yoidnfL0u6RC0fbSnZ2dnUVZ_r6dnZ2d@bestweb.net>
In reply to#18940
On 3/22/2012 6:22 AM, James Kuyper wrote:
> On 03/22/2012 12:53 AM, Stephen Sprunk wrote:
>> On 21-Mar-12 19:24, James Kuyper wrote:
>>> On 03/21/2012 06:58 PM, Stephen Sprunk wrote:
>>>> On 20-Mar-12 17:37, James Kuyper wrote:
[... optimizers / address of variables ...]
>>> I don't follow that - why would a situation that renders it unnecessary
>>> to store a variable in addressable memory imply that it's unnecessary to
>>> store it anywhere?
>>
>> Concrete example:
>>
>> int quux(void)
>> {
>>    int foo = 42;
>>    int *bar =&foo;
>>    return foo;
>> }
>>
>> 1. Both foo and bar start out in memory.
>> 2. foo can't be migrated to a register because of the&foo.
>> 3. bar is eliminated via dead code elimination.
>> 4. foo can now be migrated to a register.
>> 5. No address is needed for either foo or bar.
>
> A prime example of a situation where neither foo, nor bar, nor the
> address of foo, are needed.

In fact, foo itself becomes unnecessary.  My compiler optimizes this to the 
equivalent of "return 42;".

>> OTOH, say you have this:
>>
>> #include<stdio.h>
>> int quux(void)
>> {
>>    int foo = 42;
>>    int *bar =&foo;
>>    printf("%p\n", (void*)bar);
>>    return foo;
>> }
>>
>> 1. Both foo and bar start out in memory.
>> 2. foo can't be migrated to a register because of the&foo.
>> 3. bar is migrated to a register.
>> 4. An address is needed for foo but not for bar.
>>
>> Can you give a similar example for what you're describing--and your
>> mental model of what a compiler would do with it?
>
> Yes, the second case you've just given fits what I'm talking about
> exactly. Having recognized that there's absolutely no need to store 42
> anywhere, the compiler reserves an arbitrary address for foo, but never
> bothers storing anything at that address. That address is stored in a

Note that this is only due to the "special knowledge" that the compiler may 
have for the printf() function.  Had the line been this:

     plugh("%p\n", (void *)bar);

instead, then the assumption that the address will never be dereferenced 
would be invalid, and the 42 must be stored there.

Note, however, that even with the plugh() call, my compiler has still 
eliminated bar entirely, and simply passes &foo directly.  (In both cases, 
however, my compiler stores the 42.)

> register and passed to printf(), and is used for no other purpose. The
> compiler need only ensure that the address is not used for any other
> object that might have a lifetime that overlaps the call to quux(),
> which is something it would have had to do anyway, if 42 had been stored
> there.
[...]

-- 
Kenneth Brody

[toc] | [prev] | [next] | [standalone]


#19009

FromStephen Sprunk <stephen@sprunk.org>
Date2012-03-24 16:09 -0500
Message-ID<jkld5d$jad$1@dont-email.me>
In reply to#18942
On 22-Mar-12 11:01, Kenneth Brody wrote:
> On 3/22/2012 6:22 AM, James Kuyper wrote:
>> On 03/22/2012 12:53 AM, Stephen Sprunk wrote:
>>> Concrete example:
>>>
>>> int quux(void)
>>> {
>>>    int foo = 42;
>>>    int *bar =&foo;
>>>    return foo;
>>> }
>>>
>>> 1. Both foo and bar start out in memory.
>>> 2. foo can't be migrated to a register because of the&foo.
>>> 3. bar is eliminated via dead code elimination.
>>> 4. foo can now be migrated to a register.
>>> 5. No address is needed for either foo or bar.
>>
>> A prime example of a situation where neither foo, nor bar, nor the
>> address of foo, are needed.
> 
> In fact, foo itself becomes unnecessary.  My compiler optimizes this to
> the equivalent of "return 42;".

True in theory, but every implementation I'm familiar with passes the
return value in a register, so the output is the same whether the
compiler eliminates foo or not.

>>> OTOH, say you have this:
>>>
>>> #include<stdio.h>
>>> int quux(void)
>>> {
>>>    int foo = 42;
>>>    int *bar =&foo;
>>>    printf("%p\n", (void*)bar);
>>>    return foo;
>>> }
>>>
>>> 1. Both foo and bar start out in memory.
>>> 2. foo can't be migrated to a register because of the&foo.
>>> 3. bar is migrated to a register.
>>> 4. An address is needed for foo but not for bar.
>>>
>>> Can you give a similar example for what you're describing--and your
>>> mental model of what a compiler would do with it?
>>
>> Yes, the second case you've just given fits what I'm talking about
>> exactly. Having recognized that there's absolutely no need to store 42
>> anywhere, the compiler reserves an arbitrary address for foo, but never
>> bothers storing anything at that address. That address is stored in a
> 
> Note that this is only due to the "special knowledge" that the compiler
> may have for the printf() function.  Had the line been this:
> 
>     plugh("%p\n", (void *)bar);
> 
> instead, then the assumption that the address will never be dereferenced
> would be invalid, and the 42 must be stored there.

Exactly my point.

> Note, however, that even with the plugh() call, my compiler has still
> eliminated bar entirely, and simply passes &foo directly.  (In both
> cases, however, my compiler stores the 42.)

Good point; I was thinking of systems where arguments are passed in
registers or must be in a register to be pushed onto the stack.  If
neither of those applies, bar can be eliminated.

S

-- 
Stephen Sprunk         "God does not play dice."  --Albert Einstein
CCIE #3723         "God is an inveterate gambler, and He throws the
K5SSS        dice at every possible opportunity." --Stephen Hawking

[toc] | [prev] | [next] | [standalone]


#18951

FromJens Gustedt <jens.gustedt@loria.fr>
Date2012-03-23 13:41 +0100
Message-ID<4F6C6F61.9010508@loria.fr>
In reply to#18940
Hello,

Am 03/22/2012 11:22 AM, schrieb James Kuyper:
> Note: I'm winging it on that last statement. I've not had time to
> assimilate C's new support for multi-threaded code. If there's some way
> to guarantee that a scanf() call followed by a dereference in some other
> part of the program will be executed between the printf() and the return
> in quux(), then I'm wrong.

has nothing to do with threads. printf is a library function, yes, but
there is no guarantee, I think that it has no right to at least
inspect the contents that the argument is pointing to.


> But I'd expect that the ability to guarantee
> such sequencing would require executing a call to one of the new
> thread-related functions between the printf() and the return. Code where
> such sequencing is merely possible, but not guaranteed, has undefined
> behavior if it doesn't execute in that sequence, thereby allowing the
> optimization.

No. The other thread could know by some other magic when doing this
if the thread here still is alive and thus the pointer is still
valid. (E.g all threads might be serialized and the other thread can
inspect a table of all running threads.)

As a side note, in C11 it is implementation specific if a thread has
the right to poke into memory that resides on the stack of another
thread.

Jens

[toc] | [prev] | [next] | [standalone]


#18952

FromJames Kuyper <jameskuyper@verizon.net>
Date2012-03-23 09:06 -0400
Message-ID<jkhsgc$rnl$1@dont-email.me>
In reply to#18951
On 03/23/2012 08:41 AM, Jens Gustedt wrote:
> Hello,
> 
> Am 03/22/2012 11:22 AM, schrieb James Kuyper:
>> Note: I'm winging it on that last statement. I've not had time to
>> assimilate C's new support for multi-threaded code. If there's some way
>> to guarantee that a scanf() call followed by a dereference in some other
>> part of the program will be executed between the printf() and the return
>> in quux(), then I'm wrong.
> 
> has nothing to do with threads. printf is a library function, yes, but
> there is no guarantee, I think that it has no right to at least
> inspect the contents that the argument is pointing to.

How does "no guarantee" and "no right" fit together - or is the
guarantee you're referring something other than "printf()" is guaranteed
to not dereference the pointer?  I've routinely passed null pointers to
printf("%p") - if there's no such guarantee, that's undefined behavior.

>> But I'd expect that the ability to guarantee
>> such sequencing would require executing a call to one of the new
>> thread-related functions between the printf() and the return. Code where
>> such sequencing is merely possible, but not guaranteed, has undefined
>> behavior if it doesn't execute in that sequence, thereby allowing the
>> optimization.
> 
> No. The other thread could know by some other magic when doing this
> if the thread here still is alive and thus the pointer is still
> valid. (E.g all threads might be serialized and the other thread can
> inspect a table of all running threads.)

That's outside the scope of the C standard (unless there's some features
of the new threading library that I'm unfamiliar with - which is quite
possible). Therefore whether or not a given implementation can do the
optimization I'm talking about depends in part upon whether it provides
such mechanisms to make it invalid.
-- 
James Kuyper

[toc] | [prev] | [next] | [standalone]


#18962

FromJens Gustedt <jens.gustedt@loria.fr>
Date2012-03-23 19:47 +0100
Message-ID<4F6CC551.9040201@loria.fr>
In reply to#18952
Am 03/23/2012 02:06 PM, schrieb James Kuyper:
>> No. The other thread could know by some other magic when doing this
>> if the thread here still is alive and thus the pointer is still
>> valid. (E.g all threads might be serialized and the other thread can
>> inspect a table of all running threads.)
> 
> That's outside the scope of the C standard (unless there's some features
> of the new threading library that I'm unfamiliar with - which is quite
> possible). Therefore whether or not a given implementation can do the
> optimization I'm talking about depends in part upon whether it provides
> such mechanisms to make it invalid.

No it isn't outside the scope of the standard. Undefined behavior only
occurs when some thread effectively accesses a pointer who's object's
lifetime has ended. The only potential that such undefined behavior
might occur (or not) is not by itself undefined behavior. Whenever a
thread could access such a pointer legally the "as if" rule applies, so
the pointer must be a real thing pointing to the real data. What the
thread might use to determine that this is legal is out of the scope of
the standard.

BTW, again you don't need threads for such a discussion. Even without
threads you can have execution of other parts of the program outside the
usual control flow, e.g through a signal handler.

Jens

[toc] | [prev] | [next] | [standalone]


#18967

FromJames Kuyper <jameskuyper@verizon.net>
Date2012-03-23 16:04 -0400
Message-ID<4F6CD742.2040000@verizon.net>
In reply to#18962
On 03/23/2012 02:47 PM, Jens Gustedt wrote:
> Am 03/23/2012 02:06 PM, schrieb James Kuyper:
>>> No. The other thread could know by some other magic when doing this
>>> if the thread here still is alive and thus the pointer is still
>>> valid. (E.g all threads might be serialized and the other thread can
>>> inspect a table of all running threads.)
>>
>> That's outside the scope of the C standard (unless there's some features
>> of the new threading library that I'm unfamiliar with - which is quite
>> possible). Therefore whether or not a given implementation can do the
>> optimization I'm talking about depends in part upon whether it provides
>> such mechanisms to make it invalid.
> 
> No it isn't outside the scope of the standard. Undefined behavior only
> occurs when some thread effectively accesses a pointer who's object's
> lifetime has ended.

Correct. Therefore, an implementation which provides, as a non-standard
extension, the ability to guarantee that such code will execute during
the object's lifetime, cannot use undefined behavior as an excuse to
perform the optimization I'm talking about. However, a fully conforming
implementation that provides no such mechanism CAN perform such an
optimization. To provide such a guarantee in a portable fashion would
require a re-write to the example code; it can't exist with the code as
written.

> BTW, again you don't need threads for such a discussion. Even without
> threads you can have execution of other parts of the program outside the
> usual control flow, e.g through a signal handler.

Sure - for instance, a fully portable way to do this by modifying the
function would be to create a volatile sig_atomic_type object visible
from both this function and the signal handler, initialized to 0, set to
1 after the call to printf(), and set back to 0 before the execution of
the return statement, and modified by no other part of the program. If
the function itself is never called by a signal handler, and if the
signal handler sees that the value of that object is 1, then it can
guarantee that it's executing it's own code during the lifetime of the
object pointed at by that pointer, and can therefore safely dereference
that pointer.
Under those circumstances, the implementation would be prohibited from
performing the kind of optimization I'm talking about.

At least, that would be the case if the restrictions on what you can do
with standard-defined behavior inside a signal handler weren't so severe
(I've not had time to see if they've relaxed those restriction in C2011
- but in C99 every method I can think of for getting the address that
was printed out by printf() into the signal handler's scope would have
had undefined behavior - for one thing, it would require fflush(stdout),
and then some interaction with the user through stdin, both of which
would violate the prohibition on calling standard library functions
(7.1.4p4 and footnote 188 of n1570.pdf).

The key point is that execution of the signal handler code during the
pointed-at object's lifetime must be guaranteed, not merely a
possibility. In the absence of something that forces the access through
the pointer to be sequenced between the start and the end of the
pointed-at object's lifetime, an implementation is free to optimize the
object's lifetime down to 0 seconds, giving such code exactly 0% chance
of executing during the non-existing time interval in which
dereferencing the address would have defined behavior.

[toc] | [prev] | [next] | [standalone]


#18979

FromJens Gustedt <jens.gustedt@loria.fr>
Date2012-03-24 00:19 +0100
Message-ID<4F6D0513.60805@loria.fr>
In reply to#18967
Am 03/23/2012 09:04 PM, schrieb James Kuyper:

> At least, that would be the case if the restrictions on what you can do
> with standard-defined behavior inside a signal handler weren't so severe
> (I've not had time to see if they've relaxed those restriction in C2011

C11 adds all _Atomic qualified objects that are lock-free to the list
of objects that are allowed to be accessed.

> - but in C99 every method I can think of for getting the address that
> was printed out by printf() into the signal handler's scope would have
> had undefined behavior - for one thing, it would require fflush(stdout),
> and then some interaction with the user through stdin, both of which
> would violate the prohibition on calling standard library functions
> (7.1.4p4 and footnote 188 of n1570.pdf).

The feedback of the information (of the pointer value) must not
necessarily be through a read from a FILE*. Input can come through a
volatile qualified variable. For C99 this would have to be of type
sig_atomic_t, or if that is not wide enough you would have to stitch
together several of them to reconstruct the pointer value. For C99 a
volatile and _Atomic qualified pointer type could suffice (if it is
lockfree).

> The key point is that execution of the signal handler code during the
> pointed-at object's lifetime must be guaranteed, not merely a
> possibility.

printf is doing IO. On modern OS signal handlers kick into its
execution all the time.

key point is that for the optimization to be valid you'd have to prove
that the use of the pointer value is impossible under all
circumstances.

Jens

[toc] | [prev] | [next] | [standalone]


#18982

FromJames Kuyper <jameskuyper@verizon.net>
Date2012-03-23 22:20 -0400
Message-ID<jkjb0v$ivc$1@dont-email.me>
In reply to#18979
On 03/23/2012 07:19 PM, Jens Gustedt wrote:
> Am 03/23/2012 09:04 PM, schrieb James Kuyper:
> 
>> At least, that would be the case if the restrictions on what you can do
>> with standard-defined behavior inside a signal handler weren't so severe
>> (I've not had time to see if they've relaxed those restriction in C2011
> 
> C11 adds all _Atomic qualified objects that are lock-free to the list
> of objects that are allowed to be accessed.

I expected as much - I look forward to the day when I can afford to sit
down and study C2011 carefully enough to fully understand the meaning of
that statement. Unfortunately, that day's no likely to come any time soon.

>> - but in C99 every method I can think of for getting the address that
>> was printed out by printf() into the signal handler's scope would have
>> had undefined behavior - for one thing, it would require fflush(stdout),
>> and then some interaction with the user through stdin, both of which
>> would violate the prohibition on calling standard library functions
>> (7.1.4p4 and footnote 188 of n1570.pdf).
> 
> The feedback of the information (of the pointer value) must not
> necessarily be through a read from a FILE*. Input can come through a
> volatile qualified variable. ...

How? After the printf(), the only place that the address has been
communicated to is stdout. How do you get the address back inside the
program without engaging in I/O of some kind? Even if you're writing to
a pipe, the other end of which is connected to the same program, it's
still I/O.

....
>> The key point is that execution of the signal handler code during the
>> pointed-at object's lifetime must be guaranteed, not merely a
>> possibility.
> 
> printf is doing IO. On modern OS signal handlers kick into its
> execution all the time.

The information about the pointer's address has not been completely
communicated to stdout until after printf() has done just about
everything it needs to do.

> key point is that for the optimization to be valid you'd have to prove
> that the use of the pointer value is impossible under all
> circumstances.

More accurately, you need to prove that it impossible for the pointer
value to be retrieved by code with standard-defined behavior. Since that
behavior is defined only if the the relevant code MUST be sequenced
between the start and the end of the object's life time, the burden of
proof is on the code that supposedly achieves that result; it's not very
difficult, in many cases, such as this one, to show that there can be no
such code. At least, it's not difficult on implementations that don't
provide special additional hooks for guaranteeing that sequence.
-- 
James Kuyper

[toc] | [prev] | [next] | [standalone]


#18992

FromJens Gustedt <jens.gustedt@loria.fr>
Date2012-03-24 09:39 +0100
Message-ID<4F6D885D.3050704@loria.fr>
In reply to#18982
Am 03/24/2012 03:20 AM, schrieb James Kuyper:
> How? After the printf(), the only place that the address has been
> communicated to is stdout. How do you get the address back inside the
> program without engaging in I/O of some kind? Even if you're writing to
> a pipe, the other end of which is connected to the same program, it's
> still I/O.

A device, volatile variables were invented for that. IO is not only
done through the stdio interfaces but any variable that is declared
volatile can have values that are not predictable. An atomic
variable that is attached to an input device can play back any value
that you want to the program. And as I said this works already for C99
at least, though sig_atomic_t is not too comfortable to program with.

Jens

[toc] | [prev] | [next] | [standalone]


#18912

FromAnders Wegge Keller <wegge@wegge.dk>
Date2012-03-20 20:02 +0100
Message-ID<87y5qvyu2i.fsf@huddi.jernurt.dk>
In reply to#18872
James Kuyper <jameskuyper@verizon.net> writes:

> Sort-of. Because of the as-if principle, &variable doesn't have to
> actually identify the location (if any) where the variable is stored
> unless some other part of the program would make the failure of the
> program to store it there detectable.

 I know that I venture into the uncharted interiors of the vast tract
of C known as "implementation defined"...

 But when I go there, I can tell you that I would be extremely upset,
if I found that my friendly optimizing compiler gave me a bogus buffer
address, even if the only usage thereof the compiler can detect, is to
enter it into the struct that defines a DMA transfer.

 I would be doubly upset, if I found out that it only does this
optimization once in while.

-- 
/Wegge

Leder efter redundant peering af dk.*,linux.debian.*

[toc] | [prev] | [next] | [standalone]


#18913

FromJames Kuyper <jameskuyper@verizon.net>
Date2012-03-20 15:18 -0400
Message-ID<4F68D815.9070808@verizon.net>
In reply to#18912
On 03/20/2012 03:02 PM, Anders Wegge Keller wrote:
> James Kuyper <jameskuyper@verizon.net> writes:
> 
>> Sort-of. Because of the as-if principle, &variable doesn't have to
>> actually identify the location (if any) where the variable is stored
>> unless some other part of the program would make the failure of the
>> program to store it there detectable.
> 
>  I know that I venture into the uncharted interiors of the vast tract
> of C known as "implementation defined"...
> 
>  But when I go there, I can tell you that I would be extremely upset,
> if I found that my friendly optimizing compiler gave me a bogus buffer
> address, even if the only usage thereof the compiler can detect, is to
> enter it into the struct that defines a DMA transfer.

DMA transfer is outside the scope of the C standard, so I didn't word my
statement quite right to cover that possibility, but that basically
falls under the category of "some other part of the program would make
the failure of the program to store it there detectable".

[toc] | [prev] | [next] | [standalone]


#18934

FromAnders Wegge Keller <wegge@wegge.dk>
Date2012-03-21 21:37 +0100
Message-ID<873991y9k6.fsf@huddi.jernurt.dk>
In reply to#18913
James Kuyper <jameskuyper@verizon.net> writes:

> On 03/20/2012 03:02 PM, Anders Wegge Keller wrote:

>>  I know that I venture into the uncharted interiors of the vast tract
>> of C known as "implementation defined"...

 ...

> DMA transfer is outside the scope of the C standard,

 I know, and I'm not trying to tell you otherwise. 

> so I didn't word my statement quite right to cover that possibility,
> but that basically falls under the category of "some other part of
> the program would make the failure of the program to store it there
> detectable".

 That would cover it.

-- 
/Wegge

Leder efter redundant peering af dk.*,linux.debian.*

[toc] | [prev] | [next] | [standalone]


#18905

FromLowell Gilbert <lgusenet@be-well.ilk.org>
Date2012-03-20 11:52 -0400
Message-ID<44y5qv46e7.fsf@lowell-desk.lan>
In reply to#18871
Stephen Sprunk <stephen@sprunk.org> writes:

> On 19-Mar-12 09:52, Lowell Gilbert wrote:
>> Zero <chefmuetze@web.de> writes:
>>> Thank you!
>> 
>> Note, however, that by printing the addresses, that code may have
>> changed how the compiler would otherwise have stored the variables.
>
> The Uncertainty Principle applied to C?  Good job!

Not a metaphor that would have occurred to me, but cute.

>> This isn't just compiler-dependent; it tends to be very sensitive to
>> optimization, as well.
>
> Indeed; this is a very basic optimization.  Any decent compiler will try
> to eliminate variables, where possible, and to store the ones it can't
> in registers.  Taking the address of a variable, though, forces that
> variable to be stored in memory.

Agreed, but I was getting at a bit more than that.  Even once the
variable has been forced into memory by using the '&' operator,
different kinds of optimizations may well result in it being stored 
at different places in memory.

This isn't a pedantic issue; it's commonplace to see a memory map
change when you recompile with different options. It's only a
problem if you forget to pick up the new map, but it *does* mean the
map may change in ways the programmer can't always work out from
first principles. Fortunately, the compiler can usually be convinced
to tell you.

-- 
Lowell Gilbert, embedded/networking software engineer
	 http://be-well.ilk.org/~lowell/

[toc] | [prev] | [next] | [standalone]


#18926

FromKenneth Brody <kenbrody@spamcop.net>
Date2012-03-21 11:04 -0400
Message-ID<OJydnQxD8sFtcPTSnZ2dnUVZ_vGdnZ2d@bestweb.net>
In reply to#18905
On 3/20/2012 11:52 AM, Lowell Gilbert wrote:
> Stephen Sprunk<stephen@sprunk.org>  writes:
>
>> On 19-Mar-12 09:52, Lowell Gilbert wrote:
>>> Zero<chefmuetze@web.de>  writes:
>>>> Thank you!
>>>
>>> Note, however, that by printing the addresses, that code may have
>>> changed how the compiler would otherwise have stored the variables.
>>
>> The Uncertainty Principle applied to C?  Good job!
>
> Not a metaphor that would have occurred to me, but cute.

You've apparently never heard of a Heisenbug?

>>> This isn't just compiler-dependent; it tends to be very sensitive to
>>> optimization, as well.
>>
>> Indeed; this is a very basic optimization.  Any decent compiler will try
>> to eliminate variables, where possible, and to store the ones it can't
>> in registers.  Taking the address of a variable, though, forces that
>> variable to be stored in memory.
>
> Agreed, but I was getting at a bit more than that.  Even once the
> variable has been forced into memory by using the '&' operator,
> different kinds of optimizations may well result in it being stored
> at different places in memory.
>
> This isn't a pedantic issue; it's commonplace to see a memory map
> change when you recompile with different options. It's only a
> problem if you forget to pick up the new map, but it *does* mean the
> map may change in ways the programmer can't always work out from
> first principles. Fortunately, the compiler can usually be convinced
> to tell you.

Unless you're tracking down a bug related to the variable's address (perhaps 
it gets placed at the end of memory with one set of options, causing a 
buffer overrun to crash the program, whereas it's not at the end of memory 
with other options, causing the buffer overrun to cause hidden problems 
instead), I don't see where "it being stored at different places in memory" 
becomes an issue.

-- 
Kenneth Brody

[toc] | [prev] | [standalone]


Page 2 of 2 — ← Prev page 1 [2]

Back to top | Article view | comp.lang.c


csiph-web