473,387 Members | 1,541 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,387 software developers and data experts.

Odd behavior with odd code

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

int main( int argc , char ** argv )
{
looper:
printf( "%d\n" , argc ) ;
printf( "%x\n" , &&looper ) ;
if( argc 0 )
((int(*)(int,char**))&&looper)( 0 , argv ) ;
return 0 ;
}

Linux version 2.6.17-10-386 (root@vernadsky) (gcc version 4.1.2
20060928 (prerelease) (Ubuntu 4.1.1-13ubuntu5)) #2 Fri Oct 13 18:41:40
UTC 2006 (Ubuntu 2.6.17-10.33-386)

gcc version 4.1.2 20060928 (prerelease) (Ubuntu 4.1.1-13ubuntu5)

On this box the code above compiles but runs in an infinite loop.
Instead of pushing the stack pointer and calling the label location as
a function with the arguments given as I expected, the compiler
instead acts as though it was a simple goto and reuses the original
arguments.

gdb backtrace sees only a single frame.

Feb 16 '07 #1
33 1881
Michael Speer wrote:
#include <stdio.h>
#include <stdlib.h>

int main( int argc , char ** argv )
{
looper:
printf( "%d\n" , argc ) ;
printf( "%x\n" , &&looper ) ;
if( argc 0 )
((int(*)(int,char**))&&looper)( 0 , argv ) ;
return 0 ;
}

Linux version 2.6.17-10-386 (root@vernadsky) (gcc version 4.1.2
20060928 (prerelease) (Ubuntu 4.1.1-13ubuntu5)) #2 Fri Oct 13 18:41:40
UTC 2006 (Ubuntu 2.6.17-10.33-386)

gcc version 4.1.2 20060928 (prerelease) (Ubuntu 4.1.1-13ubuntu5)

On this box the code above compiles but runs in an infinite loop.
Instead of pushing the stack pointer and calling the label location as
a function with the arguments given as I expected, the compiler
instead acts as though it was a simple goto and reuses the original
arguments.

gdb backtrace sees only a single frame.
This group discusses ISO C. Your code uses gcc specific extensions and
thus it's behaviour is outside the scope of this group. Maybe a gcc
mailing list or group would be more appropriate.

Feb 16 '07 #2
In article <11*********************@v45g2000cwv.googlegroups. com>,
Michael Speer <kn*******@gmail.comwrote:
>#include <stdio.h>
#include <stdlib.h>
You do not appear to be using anything from stdlib.h
>int main( int argc , char ** argv )
{
looper:
printf( "%d\n" , argc ) ;
printf( "%x\n" , &&looper ) ;
A label is not an object, and cannot have its address taken.
A label is not even in the same namespace as objects.

If you did manage to take the address of a label, then
a %x format would not be the correct format with which to print
out the address. You need %p to print out pointers.
if( argc 0 )
((int(*)(int,char**))&&looper)( 0 , argv ) ;
return 0 ;
}
>Linux version 2.6.17-10-386 (root@vernadsky) (gcc version 4.1.2
20060928 (prerelease) (Ubuntu 4.1.1-13ubuntu5)) #2 Fri Oct 13 18:41:40
UTC 2006 (Ubuntu 2.6.17-10.33-386)

gcc version 4.1.2 20060928 (prerelease) (Ubuntu 4.1.1-13ubuntu5)

On this box the code above compiles but runs in an infinite loop.
You didn't compile with C, you compiled with gcc. gcc implements
a C-like language, but does not implement C unless you use a
number of compile options to force it to compile the way a C compiler
should. For assistance with the C-like language implemented
by gcc, you would need to ask in a gcc newsgroup. (You won't be
able to compile your program as real C.)
>Instead of pushing the stack pointer and calling the label location as
a function with the arguments given as I expected, the compiler
instead acts as though it was a simple goto and reuses the original
arguments.
Anything can happen when you violate C semantics.

--
Okay, buzzwords only. Two syllables, tops. -- Laurie Anderson
Feb 16 '07 #3
"Michael Speer" <kn*******@gmail.comwrote:
>#include <stdio.h>
#include <stdlib.h>

int main( int argc , char ** argv )
{
looper:
printf( "%d\n" , argc ) ;
printf( "%x\n" , &&looper ) ;
if( argc 0 )
((int(*)(int,char**))&&looper)( 0 , argv ) ;
return 0 ;
}
...

On this box the code above compiles but runs in an infinite loop.
Instead of pushing the stack pointer and calling the label location as
a function with the arguments given as I expected, the compiler
instead acts as though it was a simple goto and reuses the original
arguments.
I don't understand what is the meaning of &&looper, "the address of
the address of a label?". A label is neither a function nor an object,
so the unary & can not be applied to it. It this program produced
"expected results" in some other system that is sheer luck. (Or lack
thereof)
From WG14/N1124 Committee Draft — May 6, 2005 ISO/IEC 9899:TC2

6.5.3.2 Address and indirection operators

Constraints

1 The operand of the unary & operator shall be either a function
designator, the result of a [] or unary * operator, or an lvalue that
designates an object that is not a bit-field and is not declared with
the register storage-class specifier.

2 The operand of the unary * operator shall have pointer type.

Semantics

3 The unary & operator yields the address of its operand. If the
operand has type ‘‘type’’, the result has type ‘‘pointer to type’’. If
the operand is the result of a unary * operator, neither that operator
nor the & operator is evaluated and the result is as if both were
omitted, except that the constraints on the operators still apply and
the result is not an lvalue. Similarly, if the operand is the result
of a [] operator, neither the & operator nor the unary * that is
implied by the [] is evaluated and the result is as if the & operator
were removed and the [] operator were changed to a + operator.
Otherwise, the result is a pointer to the object or function
designated by its operand.

Roberto Waltman

[ Please reply to the group,
return address is invalid ]
Feb 16 '07 #4
Roberto Waltman wrote:
"Michael Speer" <kn*******@gmail.comwrote:
#include <stdio.h>
#include <stdlib.h>

int main( int argc , char ** argv )
{
looper:
printf( "%d\n" , argc ) ;
printf( "%x\n" , &&looper ) ;
if( argc 0 )
((int(*)(int,char**))&&looper)( 0 , argv ) ;
return 0 ;
}
...

On this box the code above compiles but runs in an infinite loop.
Instead of pushing the stack pointer and calling the label location as
a function with the arguments given as I expected, the compiler
instead acts as though it was a simple goto and reuses the original
arguments.

I don't understand what is the meaning of &&looper, "the address of
the address of a label?". A label is neither a function nor an object,
so the unary & can not be applied to it. It this program produced
"expected results" in some other system that is sheer luck. (Or lack
thereof)
It's not two instances of &, but it's one instance of &&, just like
how ++1 is invalid even though it would make sense if read as + + 1.
And the use of && as a unary operator applied to a label is a compiler
extension for which a diagnostic is correctly issued in conforming
mode.

Feb 16 '07 #5

Santosh : I will not bother this group again with problems that
apparently do not extend to C but in.

Walter : on my system the sizeof( int ) == sizeof( pointer ) and
pointers are printed in hex so it printed the same, though I know it
is not guaranteed. Thank you for pointing out the appropriate %p
format symbol. Your insight of gcc implementing a C-like language
that deviates from the standard is also welcomed.

Roberto : I do not know why &&label takes the address of the label,
but it seems to do so readily. It is likely, judging from Santosh, a
gcc extension or a fluke. I got this informations from another thread
from which the explanation was absent.

Thank you for your comments.

Feb 16 '07 #6
"Michael Speer" wrote:
>...
Roberto : I do not know why &&label takes the address of the label,
but it seems to do so readily. It is likely, judging from Santosh, a
gcc extension or a fluke...
I learned something new: This is GCC extension.

From

http://gcc.gnu.org/onlinedocs/gcc-4....bels-as-Values

5.3 Labels as Values

You can get the address of a label defined in the
current function (or a containing function) with
the unary operator `&&' ...

Sorry, can not help with your original question...
Roberto Waltman

[ Please reply to the group,
return address is invalid ]
Feb 16 '07 #7
Michael Speer wrote:
>
#include <stdio.h>
#include <stdlib.h>

int main( int argc , char ** argv )
{
looper:
printf( "%d\n" , argc ) ;
printf( "%x\n" , &&looper ) ;
if( argc 0 )
((int(*)(int,char**))&&looper)( 0 , argv ) ;
return 0 ;
}
Why this contortion? Why not simply:

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

int main(int argc, char ** argv) {
printf( "%d\n" , argc ) ;
if(argc 0) return main(0, argv)
return 0 ;
}

--
<http://www.cs.auckland.ac.nz/~pgut001/pubs/vista_cost.txt>
<http://www.securityfocus.com/columnists/423>

"A man who is right every time is not likely to do very much."
-- Francis Crick, co-discover of DNA
"There is nothing more amazing than stupidity in action."
-- Thomas Matthews
Feb 16 '07 #8
Roberto Waltman <us****@rwaltman.netwrites:
"Michael Speer" <kn*******@gmail.comwrote:
>>#include <stdio.h>
#include <stdlib.h>

int main( int argc , char ** argv )
{
looper:
printf( "%d\n" , argc ) ;
printf( "%x\n" , &&looper ) ;
if( argc 0 )
((int(*)(int,char**))&&looper)( 0 , argv ) ;
return 0 ;
}
...

On this box the code above compiles but runs in an infinite loop.
Instead of pushing the stack pointer and calling the label location as
a function with the arguments given as I expected, the compiler
instead acts as though it was a simple goto and reuses the original
arguments.

I don't understand what is the meaning of &&looper, "the address of
the address of a label?". A label is neither a function nor an object,
so the unary & can not be applied to it. It this program produced
"expected results" in some other system that is sheer luck. (Or lack
thereof)
[...]

That's actually the "&&" operator, a gcc extension that takes the
address of a label and yields a result of type void*.

Allowing conversion of a value of type void* to a pointer-to-function
type is also a gcc extension.

See the gcc documentation or gnu.gcc.help for more information.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Feb 16 '07 #9
Keith Thompson <ks***@mib.orgwrote:
>Roberto Waltman <us****@rwaltman.netwrites:
>>
I don't understand what is the meaning of &&looper, "the address of
the address of a label?"...

That's actually the "&&" operator, a gcc extension that takes the
address of a label and yields a result of type void*.
...
See the gcc documentation or gnu.gcc.help for more information.
Thanks, I already did. Harald van D?k and Michael Speer pointed in
that direction.
I have used gcc in several projects, but always as gcc -ansi -Wall
-pedantic -std= ...
Roberto Waltman

[ Please reply to the group,
return address is invalid ]
Feb 16 '07 #10
In article <45***************@yahoo.com>,
CBFalconer <cb********@maineline.netwrote:
>int main( int argc , char ** argv )
{
looper:
printf( "%d\n" , argc ) ;
printf( "%x\n" , &&looper ) ;
if( argc 0 )
((int(*)(int,char**))&&looper)( 0 , argv ) ;
return 0 ;
}
>Why this contortion? Why not simply:

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

int main(int argc, char ** argv) {
printf( "%d\n" , argc ) ;
if(argc 0) return main(0, argv)
return 0 ;
}
Presumably that doesn't exhibit the "bug" of looping indefinitely.

-- Richard
--
"Consideration shall be given to the need for as many as 32 characters
in some alphabets" - X3.4, 1963.
Feb 16 '07 #11
CBFalconer : I was thinking of writing a hack that would allow me to
store the label addresses in order to call a function starting at a
midway point. If I then stored static variables in a structure
outside of the list than I could create a very simple generator-like
function that starts in a different spot each time it is called
without using a switch or even recurses back to different points
within itself. Basically I was playing at what I could make the code
do. Not production.

Keith Thompson : Thank you for the information. I did not come across
it until after posting.

Just for the information of anyone here that wants it :

While compiling this code with no options or -O0 ( gcc optimization
zero ) caused it to fall into a recursive loop ( seemingly from
treating the function call as a goto ) , compiling it as -O6 ( gcc
maximum optimization ) caused it to work, redoing the stack to hold
the parameters properly.

Thank you for your comments.

Feb 16 '07 #12
Michael Speer wrote:
CBFalconer : I was thinking of writing a hack that would allow me to
store the label addresses in order to call a function starting at a
midway point. If I then stored static variables in a structure
outside of the list than I could create a very simple generator-like
function that starts in a different spot each time it is called
without using a switch or even recurses back to different points
within itself. Basically I was playing at what I could make the code
do. Not production.
Are you trying to implement coroutines?

--
Ian Collins.
Feb 16 '07 #13
On Feb 16, 5:55 pm, Ian Collins <ian-n...@hotmail.comwrote:
>
Are you trying to implement coroutines?

--
Ian Collins.
The whole of my immediate intent was to discern if it was even
possible to take the address of a label and use casting to access the
code in a function at an intermediate point. I had ideas ( the
generator or partial recursion ) of things it might be used for. From
what I know of them coroutines would be something that could be
implemented using this type of behavior. That is, if one wished to
implement them by way of the misuse of a gcc extension that when
misused thusly only compiles with the `-O6' switch being passed to the
compiler. :)

Feb 17 '07 #14
Michael Speer wrote:
>
CBFalconer : I was thinking of writing a hack that would allow me to
store the label addresses in order to call a function starting at a
midway point. If I then stored static variables in a structure
outside of the list than I could create a very simple generator-like
function that starts in a different spot each time it is called
without using a switch or even recurses back to different points
within itself. Basically I was playing at what I could make the code
do. Not production.

Keith Thompson : Thank you for the information. I did not come across
it until after posting.
I never wrote anything as foolish as that. I have similar doubts
about Keiths authorship, but we'll let him speak for himself. If
you just use proper Usenet quoting this sort of foul-up will have a
hard time occurring.

--
<http://www.cs.auckland.ac.nz/~pgut001/pubs/vista_cost.txt>
<http://www.securityfocus.com/columnists/423>

"A man who is right every time is not likely to do very much."
-- Francis Crick, co-discover of DNA
"There is nothing more amazing than stupidity in action."
-- Thomas Matthews
Feb 17 '07 #15
CBFalconer <cb********@yahoo.comwrites:
Michael Speer wrote:
>>
CBFalconer : I was thinking of writing a hack that would allow me to
store the label addresses in order to call a function starting at a
midway point. If I then stored static variables in a structure
outside of the list than I could create a very simple generator-like
function that starts in a different spot each time it is called
without using a switch or even recurses back to different points
within itself. Basically I was playing at what I could make the code
do. Not production.

Keith Thompson : Thank you for the information. I did not come across
it until after posting.

I never wrote anything as foolish as that. I have similar doubts
about Keiths authorship, but we'll let him speak for himself. If
you just use proper Usenet quoting this sort of foul-up will have a
hard time occurring.
The strings "CBFalconer :" and "Keith Thompson :" were, I'm sure,
intended to address the following comments to us, not to imply that we
had written them. (Note the lack of the word "wrote", or "writes", or
anything similar).

Posting separate followups quoting (some of) what each of us had
written would have been more in keeping with usual Usenet practice,
but combining both in a single followup is not horrid IMHO. The
prefixes don't particularly look (to me) like attribution lines.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Feb 17 '07 #16
In article <11**********************@q2g2000cwa.googlegroups. com>
Michael Speer <kn*******@gmail.comwrote:
>While compiling this code
[which, as a reminder that should also make this article stand-alone,
was some code using gcc-specific extensions in ways other than those
intended by the gcc-extension authors, in my opinion anyway]
>with no options or -O0 ( gcc optimization zero ) caused it to fall
into a recursive loop ( seemingly from treating the function call
as a goto ) , compiling it as -O6 ( gcc maximum optimization )
caused it to work, redoing the stack to hold the parameters properly.
That implies that either or both of the following are true:

- gcc has a bug in dealing with this extension, or
- you are not using the extension in a way that even gcc defines
(i.e., you are invoking not only undefined-by-the-C-standard
behavior, but even undefined-by-gcc-extension behavior).

I believe the latter is true. The former may or may not also be
true.
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Feb 17 '07 #17

"Roberto Waltman" <us****@rwaltman.netwrote in message
news:o9********************************@4ax.com...
http://gcc.gnu.org/onlinedocs/gcc-4....bels-as-Values

5.3 Labels as Values

You can get the address of a label defined in the
current function (or a containing function) with
the unary operator `&&' ...

Sorry, can not help with your original question...
seems like a useless feature to me. even in that article they recommend
"just use switch"
Feb 17 '07 #18
"Michael Speer" <kn*******@gmail.comwrote in message
news:11**********************@q2g2000cwa.googlegro ups.com...
On Feb 16, 5:55 pm, Ian Collins <ian-n...@hotmail.comwrote:
>Are you trying to implement coroutines?

The whole of my immediate intent was to discern if it was even
possible to take the address of a label and use casting to access the
code in a function at an intermediate point. I had ideas ( the
generator or partial recursion ) of things it might be used for. From
what I know of them coroutines would be something that could be
implemented using this type of behavior.
The problem with casting a pointer-to-label to a pointer-to-function is that
a label is not a function. The beginning of a function contains a prologue
which builds the appropriate stack frame, retrieves arguments from wherever
they are, etc. The compiler doesn't know it needs to do that at a label
used as a function entry point -- in fact it probably can't do it even if it
does know it needs to, since you can (usually) arrive at the label when it's
_not_ being used as a function entry point.

My guess is that this extension was created so that labels could be stored
in variables and one could later do "goto variable;", Since there's no
pointer-to-label type, void* is the logical choice for this abuse -- but you
need some sort of construct to turn it back into a pointer-to-label (which
I'm assuming goto can do) to actually make use of it. Instead, you're
turning that pointer-to-object (which is really a pointer-to-label) into a
pointer-to-function and trying to call it, which is so far out there it's
not even just "wrong".

There's probably a portable way to implement whatever you're trying to do;
give us the problem first, not the solution, and we can try to help.

S

--
Stephen Sprunk "Those people who think they know everything
CCIE #3723 are a great annoyance to those of us who do."
K5SSS --Isaac Asimov

--
Posted via a free Usenet account from http://www.teranews.com

Feb 17 '07 #19
Stephen Sprunk wrote:
"Michael Speer" <kn*******@gmail.comwrote in message
news:11**********************@q2g2000cwa.googlegro ups.com...
On Feb 16, 5:55 pm, Ian Collins <ian-n...@hotmail.comwrote:
Are you trying to implement coroutines?
The whole of my immediate intent was to discern if it was even
possible to take the address of a label and use casting to access the
code in a function at an intermediate point. I had ideas ( the
generator or partial recursion ) of things it might be used for. From
what I know of them coroutines would be something that could be
implemented using this type of behavior.

The problem with casting a pointer-to-label to a pointer-to-function is that
a label is not a function. The beginning of a function contains a prologue
which builds the appropriate stack frame, retrieves arguments from wherever
they are, etc. The compiler doesn't know it needs to do that at a label
used as a function entry point -- in fact it probably can't do it even if it
does know it needs to, since you can (usually) arrive at the label when it's
_not_ being used as a function entry point.

My guess is that this extension was created so that labels could be stored
in variables and one could later do "goto variable;",
A compiler must treat

void f(void) {
void *p;
goto p;
p:
return;
}

as a jump to label p, not to the address referenced by variable p.

[OT] In "GNU C", the syntax for a jump to a stored address is goto *p;
[/OT]

Feb 17 '07 #20
On Feb 17, 2:05 pm, "Stephen Sprunk" <step...@sprunk.orgwrote:
"Michael Speer" <knome....@gmail.comwrote in message

news:11**********************@q2g2000cwa.googlegro ups.com...
On Feb 16, 5:55 pm, Ian Collins <ian-n...@hotmail.comwrote:
Are you trying to implement coroutines?
The whole of my immediate intent was to discern if it was even
possible to take the address of a label and use casting to access the
code in a function at an intermediate point. I had ideas ( the
generator or partial recursion ) of things it might be used for. From
what I know of them coroutines would be something that could be
implemented using this type of behavior.

The problem with casting a pointer-to-label to a pointer-to-function is that
a label is not a function. The beginning of a function contains a prologue
which builds the appropriate stack frame, retrieves arguments from wherever
they are, etc.
I my understanding of the cdecl convention it states the code calling
the function sets up the arguments for the stack frame then calls the
function. Then the call command pushes the current base and stack
registers onto the stack. Then only local variables would require the
base and stack pointers to be moved again. The ret command undoes the
stack frame register push on the stack. Finally the calling code
undoes the argument push and the frame is back where it started.

So the code in the function itself need only create local variables.
So using the my hack above should break on functions that have local
variables, but not ones that do not.

So it should work to jump in halfway, as long as there are no local
variables that would have missed being setup.
The compiler doesn't know it needs to do that at a label
used as a function entry point -- in fact it probably can't do it even if it
does know it needs to, since you can (usually) arrive at the label when it's
_not_ being used as a function entry point.
To the compiler it should not matter. I have told the compiler
through casting that my label points to a function entry taking an int
and char** argument set, so it should do a normal cdecl argument push
and call the address at the label.
My guess is that this extension was created so that labels could be stored
in variables and one could later do "goto variable;",
... which is so far out there it's
not even just "wrong".
Correct on both accusations. In defense of the hack, a pointer to a
memory location is a pointer to a memory location. There aren't
actually pointers to objects, functions, labels, etc. Just pointers
that we inform the compiler will be used for these purposes so it
knows how to setup any pointer arithmetic as it needs to do. Outside
of that, one could goto 0x08374322 and it should work, if the code
they want to jump to is really located at that point.
>
There's probably a portable way to implement whatever you're trying to do;
give us the problem first, not the solution, and we can try to help.

S
Unfortunately this is a solution without a problem. Or a problem
starting with the phrase "I wonder if I could...", depending on how
you look at it.
>
--
Stephen Sprunk "Those people who think they know everything
CCIE #3723 are a great annoyance to those of us who do."
K5SSS --Isaac Asimov

--
Posted via a free Usenet account fromhttp://www.teranews.com
Feb 17 '07 #21
On Feb 17, 2:26 pm, "Harald van Dijk" <true...@gmail.comwrote:
Stephen Sprunk wrote:
"Michael Speer" <knome....@gmail.comwrote in message
news:11**********************@q2g2000cwa.googlegro ups.com...
On Feb 16, 5:55 pm, Ian Collins <ian-n...@hotmail.comwrote:
>Are you trying to implement coroutines?
The whole of my immediate intent was to discern if it was even
possible to take the address of a label and use casting to access the
code in a function at an intermediate point. I had ideas ( the
generator or partial recursion ) of things it might be used for. From
what I know of them coroutines would be something that could be
implemented using this type of behavior.
The problem with casting a pointer-to-label to a pointer-to-function isthat
a label is not a function. The beginning of a function contains a prologue
which builds the appropriate stack frame, retrieves arguments from wherever
they are, etc. The compiler doesn't know it needs to do that at a label
used as a function entry point -- in fact it probably can't do it even if it
does know it needs to, since you can (usually) arrive at the label whenit's
_not_ being used as a function entry point.
My guess is that this extension was created so that labels could be stored
in variables and one could later do "goto variable;",

A compiler must treat

void f(void) {
void *p;
goto p;
p:
return;

}

as a jump to label p, not to the address referenced by variable p.

[OT] In "GNU C", the syntax for a jump to a stored address is goto *p;
[/OT]
gcc allows `goto address' using the `&&' operator to take the address
of a label. It was intended to allow a programmer to store addresses
in an array and then `goto label_array[ 3 ] ;' which is presumably
faster than a switch would be as the assembly for a switch would have
to check a series of values for equivalence waiting to jump to the
address specified by the first match.

Of course, with this behavior being an extension of C, it is doubtful
to me that this sort of code is common anywhere at all. Merely
possible.

Feb 17 '07 #22
Michael Speer wrote:
On Feb 17, 2:26 pm, "Harald van Dijk" <true...@gmail.comwrote:
Stephen Sprunk wrote:
"Michael Speer" <knome....@gmail.comwrote in message
>news:11**********************@q2g2000cwa.googlegr oups.com...
On Feb 16, 5:55 pm, Ian Collins <ian-n...@hotmail.comwrote:
Are you trying to implement coroutines?
The whole of my immediate intent was to discern if it was even
possible to take the address of a label and use casting to access the
code in a function at an intermediate point. I had ideas ( the
generator or partial recursion ) of things it might be used for. From
what I know of them coroutines would be something that could be
implemented using this type of behavior.
The problem with casting a pointer-to-label to a pointer-to-function is that
a label is not a function. The beginning of a function contains a prologue
which builds the appropriate stack frame, retrieves arguments from wherever
they are, etc. The compiler doesn't know it needs to do that at a label
used as a function entry point -- in fact it probably can't do it even if it
does know it needs to, since you can (usually) arrive at the label when it's
_not_ being used as a function entry point.
My guess is that this extension was created so that labels could be stored
in variables and one could later do "goto variable;",
A compiler must treat

void f(void) {
void *p;
goto p;
p:
return;

}

as a jump to label p, not to the address referenced by variable p.

[OT] In "GNU C", the syntax for a jump to a stored address is goto *p;
[/OT]

gcc allows `goto address' using the `&&' operator to take the address
of a label.
No, it doesn't. That was the point of my previous message. It allows
`goto *address', not `goto address'.

Feb 17 '07 #23
Michael Speer wrote, On 17/02/07 20:59:
On Feb 17, 2:05 pm, "Stephen Sprunk" <step...@sprunk.orgwrote:
>"Michael Speer" <knome....@gmail.comwrote in message

news:11**********************@q2g2000cwa.googlegr oups.com...
>>On Feb 16, 5:55 pm, Ian Collins <ian-n...@hotmail.comwrote:
Are you trying to implement coroutines?
The whole of my immediate intent was to discern if it was even
possible to take the address of a label and use casting to access the
code in a function at an intermediate point. I had ideas ( the
generator or partial recursion ) of things it might be used for. From
what I know of them coroutines would be something that could be
implemented using this type of behavior.
The problem with casting a pointer-to-label to a pointer-to-function is that
a label is not a function. The beginning of a function contains a prologue
which builds the appropriate stack frame, retrieves arguments from wherever
they are, etc.

I my understanding of the cdecl convention it states the code calling
the function sets up the arguments for the stack frame then calls the
function. Then the call command pushes the current base and stack
<snip>

The C standard does not define calling conventions and a number of
different calling conventions are used even on a PC running Windows let
alone when you move beyond that in to the wide world.
>... which is so far out there it's
not even just "wrong".

Correct on both accusations. In defense of the hack, a pointer to a
memory location is a pointer to a memory location. There aren't
actually pointers to objects, functions, labels, etc. Just pointers
Wrong. I've worked on processors where data and program were in
completely separate address spaces. Others have worked on even stranger
systems.
that we inform the compiler will be used for these purposes so it
knows how to setup any pointer arithmetic as it needs to do. Outside
of that, one could goto 0x08374322 and it should work, if the code
they want to jump to is really located at that point.
The world is far more complex than you imagine.
>There's probably a portable way to implement whatever you're trying to do;
give us the problem first, not the solution, and we can try to help.

S

Unfortunately this is a solution without a problem. Or a problem
starting with the phrase "I wonder if I could...", depending on how
you look at it.
If you want to discuss what hacks you can do in your implementation then
please take it to a group dealing with your implementation.
--
Flash Gordon
Feb 17 '07 #24
"Michael Speer" <kn*******@gmail.comwrote in message
news:11*********************@l53g2000cwa.googlegro ups.com...
On Feb 17, 2:05 pm, "Stephen Sprunk" <step...@sprunk.orgwrote:
>"Michael Speer" <knome....@gmail.comwrote in message

news:11**********************@q2g2000cwa.googlegr oups.com...
On Feb 16, 5:55 pm, Ian Collins <ian-n...@hotmail.comwrote:
Are you trying to implement coroutines?
The whole of my immediate intent was to discern if it was even
possible to take the address of a label and use casting to access the
code in a function at an intermediate point. I had ideas ( the
generator or partial recursion ) of things it might be used for. From
what I know of them coroutines would be something that could be
implemented using this type of behavior.

The problem with casting a pointer-to-label to a pointer-to-function is
that
a label is not a function. The beginning of a function contains a
prologue
which builds the appropriate stack frame, retrieves arguments from
wherever
they are, etc.

I my understanding of the cdecl convention
The calling convention varies by implementation, and some implementations
even allow you to set it as a compile-time option. Making generalizations
is very tricky here. Of course, you're playing with an off-topic extension,
so you're already playing with fire.
it states the code calling the function sets up the arguments for the
stack
frame then calls the function. Then the call command pushes the current
base and stack registers onto the stack.
That's not how the ABIs I'm most familiar with work. (Assume from here down
that we're talking x86 or x64)

The caller pushes the arguments onto the stack, or stuffs them in registers,
or both. Then the CALL instruction pushes the return address onto the
stack, and jumps to the target. The callee then sets up a new stack frame
by pushing the caller's frame pointer onto the stack and moving the new
stack pointer into the frame pointer register.
Then only local variables would require the base and stack pointers to be
moved again.
The frame (or base) pointer shouldn't be changed, only the stack pointer.
The ret command undoes the stack frame register push on the stack.
Nope. The callee must pop the old frame pointer before using RET.
Finally the calling code undoes the argument push and the frame is back
where it started.
Correct.
So the code in the function itself need only create local variables.
So using the my hack above should break on functions that have local
variables, but not ones that do not.

So it should work to jump in halfway, as long as there are no local
variables that would have missed being setup.
No, it won't. Since the label isn't known to be a function entry point, it
won't have the prolog, which creates a stack frame, and it won't work as you
expect -- it'll keep using the callee's stack frame. When it returns,
provided you manage to somehow pop the correct number of locals off the
stack, it'll return to the callee, still in the same stack frame.

This is why your debugger is confused. No additional stack frames are being
created by your calls. Your callee function, no matter how many times it
recurses, are all executing with the caller's stack frame. That also means
if you access arguments in the callee, you're likely to get the caller's
arguments since they're read via the frame pointer, not the stack pointer.
It doesn't surprise me that your function recurses infinitely, since the 0
you're passing doesn't have a way to get read -- you just push another copy
of argv, 0, and the return address onto the stack with each iteration until
you run out of stack space.
>The compiler doesn't know it needs to do that at a label
used as a function entry point -- in fact it probably can't do it even if
it
does know it needs to, since you can (usually) arrive at the label when
it's
_not_ being used as a function entry point.

To the compiler it should not matter. I have told the compiler
through casting that my label points to a function entry taking an int
and char** argument set, so it should do a normal cdecl argument push
and call the address at the label.
A label, even if you could coerce it into be a function entry point, does
not take arguments. If you know the implementation details, you might be
able to retrieve them with inline asm, but there's no way for the compiler
to know to do that. Casting it to a function that takes no arguments (and
sending the data you need via one or more global variables) at least has a
tiny chance of working.
>My guess is that this extension was created so that labels could be
stored
in variables and one could later do "goto variable;",
Correction; the syntax is "goto *variable;".
>... which is so far out there it's not even just "wrong".

Correct on both accusations. In defense of the hack, a pointer to a
memory location is a pointer to a memory location. There aren't
actually pointers to objects, functions, labels, etc. Just pointers
that we inform the compiler will be used for these purposes so it
knows how to setup any pointer arithmetic as it needs to do. Outside
of that, one could goto 0x08374322 and it should work, if the code
they want to jump to is really located at that point.
Correct at the machine level, at least for many implementations, but the
compiler needs to know what type something is so it knows what instructions
to use to do interesting things with that address. If you tell it an
address is something different than it really is, you're going to get bad
results in most cases.

A function call and a goto/label pair are very, very different beasts.
Trying to coerce one into acting like the other is unlikely to work, and I'm
not sure why you'd want to try anyways. I'd be more curious to see what the
pointer-to-label extension is successfully used for and what problems it
solves, and whether it's really cleaner than something that would be more
portable.

S

--
Stephen Sprunk "Those people who think they know everything
CCIE #3723 are a great annoyance to those of us who do."
K5SSS --Isaac Asimov

--
Posted via a free Usenet account from http://www.teranews.com

Feb 17 '07 #25
On Feb 17, 4:11 pm, Flash Gordon <s...@flash-gordon.me.ukwrote:
Michael Speer wrote, On 17/02/07 20:59:
On Feb 17, 2:05 pm, "Stephen Sprunk" <step...@sprunk.orgwrote:
"Michael Speer" <knome....@gmail.comwrote in message
>news:11**********************@q2g2000cwa.googlegr oups.com...
>On Feb 16, 5:55 pm, Ian Collins <ian-n...@hotmail.comwrote:
Are you trying to implement coroutines?
The whole of my immediate intent was to discern if it was even
possible to take the address of a label and use casting to access the
code in a function at an intermediate point. I had ideas ( the
generator or partial recursion ) of things it might be used for. From
what I know of them coroutines would be something that could be
implemented using this type of behavior.
The problem with casting a pointer-to-label to a pointer-to-function is that
a label is not a function. The beginning of a function contains a prologue
which builds the appropriate stack frame, retrieves arguments from wherever
they are, etc.
I my understanding of the cdecl convention it states the code calling
the function sets up the arguments for the stack frame then calls the
function. Then the call command pushes the current base and stack

<snip>

The C standard does not define calling conventions and a number of
different calling conventions are used even on a PC running Windows let
alone when you move beyond that in to the wide world.
Point taken. My hack will only operate if the calling convention used
requires the caller to setup and take down the stack frame, leaving
the callee only having to `ret' in addition to the limitation of no
local variables I already described. In addition whatever cast is
used to force the label memory location to be treated as a function
memory location must specify the calling convention as being the same
as necessary and where possible.
... which is so far out there it's
not even just "wrong".
Correct on both accusations. In defense of the hack, a pointer to a
memory location is a pointer to a memory location. There aren't
actually pointers to objects, functions, labels, etc. Just pointers

Wrong. I've worked on processors where data and program were in
completely separate address spaces. Others have worked on even stranger
systems.
In a separate data and program memory layout, if you could take ( or
have precomputed ) the address of a label you wanted to jump to in the
program address space and then pass that value to a jmp or call then
it would operate the same. My hack does not require data and code to
overlap. I do, however, understand your point. This is not standard C
and it will not work out in the world because there are many ways the
language and standard library are implemented.
>
that we inform the compiler will be used for these purposes so it
knows how to setup any pointer arithmetic as it needs to do. Outside
of that, one could goto 0x08374322 and it should work, if the code
they want to jump to is really located at that point.

The world is far more complex than you imagine.
I agree. Aren't `labels' just markers in the code to be passed to the
assembler to be converted into memory addresses for the runtime to
jump or call to?
There's probably a portable way to implement whatever you're trying to do;
give us the problem first, not the solution, and we can try to help.
S
Unfortunately this is a solution without a problem. Or a problem
starting with the phrase "I wonder if I could...", depending on how
you look at it.

If you want to discuss what hacks you can do in your implementation then
please take it to a group dealing with your implementation.
santosh pointed this out and suggested I move to a gcc group when I
first arrived. I don't plan on continuing this indefinitely. I am
only responding to replies.
--
Flash Gordon

Feb 17 '07 #26
Michael Speer wrote:
>
.... snip ...
>
I my understanding of the cdecl convention it states the code calling
the function sets up the arguments for the stack frame then calls the
function. Then the call command pushes the current base and stack
registers onto the stack. Then only local variables would require the
base and stack pointers to be moved again. The ret command undoes the
stack frame register push on the stack. Finally the calling code
undoes the argument push and the frame is back where it started.
There is no such thing as a cdecl convention in standard C. Try a
newsgroup that deals with the peculiar system you are using.

--
<http://www.cs.auckland.ac.nz/~pgut001/pubs/vista_cost.txt>
<http://www.securityfocus.com/columnists/423>

"A man who is right every time is not likely to do very much."
-- Francis Crick, co-discover of DNA
"There is nothing more amazing than stupidity in action."
-- Thomas Matthews
Feb 18 '07 #27
"Stephen Sprunk" <st*****@sprunk.orgwrites:
"Michael Speer" <kn*******@gmail.comwrote in message
news:11**********************@q2g2000cwa.googlegro ups.com...
>On Feb 16, 5:55 pm, Ian Collins <ian-n...@hotmail.comwrote:
>>Are you trying to implement coroutines?

The whole of my immediate intent was to discern if it was even
possible to take the address of a label and use casting to access the
code in a function at an intermediate point. I had ideas ( the
generator or partial recursion ) of things it might be used for. From
what I know of them coroutines would be something that could be
implemented using this type of behavior.

The problem with casting a pointer-to-label to a pointer-to-function is that
a label is not a function.
[...]

No, the problem with casting a pointer-to-label to a
pointer-to-function is that there's no such thing in standard C as a
pointer-to-label.

If you want to ask about gcc's pointer-to-label construct, you'll need
to do so in a gcc-specific newsgroup, probably gnu.gcc.help.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Feb 18 '07 #28
"Michael Speer" <kn*******@gmail.comwrites:
On Feb 17, 4:11 pm, Flash Gordon <s...@flash-gordon.me.ukwrote:
[...]
>The world is far more complex than you imagine.

I agree. Aren't `labels' just markers in the code to be passed to the
assembler to be converted into memory addresses for the runtime to
jump or call to?
Labels are C source code constructs that can be used as the targets of
goto statements. As far as C is concerned, there is no "address"
associated with a label.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Feb 18 '07 #29
In article <11*********************@l53g2000cwa.googlegroups. com"Michael Speer" <kn*******@gmail.comwrites:
....
I my understanding of the cdecl convention it states the code calling
the function sets up the arguments for the stack frame then calls the
function. Then the call command pushes the current base and stack
registers onto the stack. Then only local variables would require the
base and stack pointers to be moved again. The ret command undoes the
stack frame register push on the stack. Finally the calling code
undoes the argument push and the frame is back where it started.
Assuming one of the many ways C allows things to be done. I know also
variations where arguments are passed through registers and the function
prologue puts them on the stack. Or where arguments are passed through
a data block that is passed to the function, which the function unpacks
in the prologue. And many more variants.
So the code in the function itself need only create local variables.
Or it may have to do with putting arguments on the stack, or whatever
else is needed.
So using the my hack above should break on functions that have local
variables, but not ones that do not.

So it should work to jump in halfway, as long as there are no local
variables that would have missed being setup.
Perhaps if there are no local variables and no arguments. Moreover, it
will fail horribly if a function pointer is larger than a void pointer.
To the compiler it should not matter. I have told the compiler
through casting that my label points to a function entry taking an int
and char** argument set, so it should do a normal cdecl argument push
and call the address at the label.
What you *assume* is a normal argument push.
--
dik t. winter, cwi, kruislaan 413, 1098 sj amsterdam, nederland, +31205924131
home: bovenover 215, 1025 jn amsterdam, nederland; http://www.cwi.nl/~dik/
Feb 18 '07 #30
On Feb 17, 5:34 pm, "Stephen Sprunk" <step...@sprunk.orgwrote:
<snip>
The caller pushes the arguments onto the stack, or stuffs them in registers,
or both. Then the CALL instruction pushes the return address onto the
stack, and jumps to the target. The callee then sets up a new stack frame
by pushing the caller's frame pointer onto the stack and moving the new
stack pointer into the frame pointer register.
Ah.
Then only local variables would require the base and stack pointers to be
moved again.

The frame (or base) pointer shouldn't be changed, only the stack pointer.
Combined with your description previous, ah ha.
The ret command undoes the stack frame register push on the stack.

Nope. The callee must pop the old frame pointer before using RET.
Makes sense given the above.

<snip>
So it should work to jump in halfway, as long as there are no local
variables that would have missed being setup.

No, it won't. Since the label isn't known to be a function entry point, it
won't have the prolog, which creates a stack frame, and it won't work as you
expect -- it'll keep using the callee's stack frame. When it returns,
provided you manage to somehow pop the correct number of locals off the
stack, it'll return to the callee, still in the same stack frame.

This is why your debugger is confused. No additional stack frames are being
created by your calls. Your callee function, no matter how many times it
recurses, are all executing with the caller's stack frame. That also means
if you access arguments in the callee, you're likely to get the caller's
arguments since they're read via the frame pointer, not the stack pointer.
It doesn't surprise me that your function recurses infinitely, since the 0
you're passing doesn't have a way to get read -- you just push another copy
of argv, 0, and the return address onto the stack with each iteration until
you run out of stack space.
That explains what it does in `-O0' mode. `-O6' must cause the label
to point to the memory location wherein the callee pushes the callers
information instead of just after as it normally does. ( the label in
the test code directly followed the function name-line ) Hence why `-
O6' seemed to work while `-O0' did not. Perhaps `-O6' took note that
there was never a goto for the label and let it fall to the same
position as the main function since there would be nothing jumping
there. Having it there then made it nothing more than a complexly
gathered function pointer, and caused the code to work because it was
now calling a genuine function entry point.

Your entire post was very insightful, and you have directly shown the
error in my calling convention assumption and why it caused the
behavior it did. Bravo, sir.

Thank you.

Feb 18 '07 #31
Dik T. Winter wrote:
In article <11*********************@l53g2000cwa.googlegroups. com"Michael Speer" <kn*******@gmail.comwrites:
...
So using the my hack above should break on functions that have local
variables, but not ones that do not.
>
So it should work to jump in halfway, as long as there are no local
variables that would have missed being setup.

Perhaps if there are no local variables and no arguments. Moreover, it
will fail horribly if a function pointer is larger than a void pointer.
If a function pointer is larger than a void pointer and void pointers
cannot meaningfully be converted to function pointers, yet the
compiler supports such conversions as an extension anyway, this is not
just useless, it's malicious. In the real world, I wouldn't worry
about such an implementation.

Feb 18 '07 #32
In article <11**********************@v33g2000cwv.googlegroups .com"Michael Speer" <kn*******@gmail.comwrites:
On Feb 17, 4:11 pm, Flash Gordon <s...@flash-gordon.me.ukwrote:
....
The C standard does not define calling conventions and a number of
different calling conventions are used even on a PC running Windows let
alone when you move beyond that in to the wide world.

Point taken. My hack will only operate if the calling convention used
requires the caller to setup and take down the stack frame, leaving
the callee only having to `ret' in addition to the limitation of no
local variables I already described.
And in addition the restriction that all arguments are passed on the stack,
and not through registers or by any other method. I do not now of *any*
implementation that follows that model.
The world is far more complex than you imagine.

I agree. Aren't `labels' just markers in the code to be passed to the
assembler to be converted into memory addresses for the runtime to
jump or call to?
In most assemblers they are still labels. And most assemblers will convert
them to relative addresses with respect to the start of the function. Then,
when a jump is executed, the assembler will determine whether it is a short
jump or a long jump (when there is such a distinction), and generate a
relative or absolute jump, where the latter is resolved by the linker. The
assembler does not know about memory addresses.
--
dik t. winter, cwi, kruislaan 413, 1098 sj amsterdam, nederland, +31205924131
home: bovenover 215, 1025 jn amsterdam, nederland; http://www.cwi.nl/~dik/
Feb 18 '07 #33
CBFalconer said:

<snip>
There is no such thing as a cdecl convention in standard C.
Yes there is - by convention, cdecl is a program for converting a type
description from C to English (or some other human language).
--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at the above domain, - www.
Feb 18 '07 #34

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

19
by: E. Robert Tisdale | last post by:
In the context of the comp.lang.c newsgroup, the term "undefined behavior" actually refers to behavior not defined by the ANSI/ISO C 9 standard. Specifically, it is *not* true that "anything can...
23
by: Ken Turkowski | last post by:
The construct (void*)(((long)ptr + 3) & ~3) worked well until now to enforce alignment of the pointer to long boundaries. However, now VC++ warns about it, undoubtedly to help things work on 64...
1
by: Jonathan Yong | last post by:
I observe a very weird behavior when dynamically create web control and bind events to it. Create a C# ASP.NET application, Put a PlaceHolder and Textbox onto the Web form, and try with the 4...
38
by: Steven Bethard | last post by:
> >>> aList = > >>> it = iter(aList) > >>> zip(it, it) > > That behavior is currently an accident. >http://sourceforge.net/tracker/?group_id=5470&atid=105470&func=detail&aid=1121416
7
by: Mike Livenspargar | last post by:
We have an application converted from v1.1 Framework to v2.0. The executable references a class library which in turn has a web reference. The web reference 'URL Behavior' is set to dynamic. We...
66
by: gyan | last post by:
Hi All, I am using sprintf and getting starnge output in following case char temp_rn; memset(temp_rn,'\0',12); sprintf(temp_rn,"0%s",temp_rn); the final value in temp_rn is 00 how it...
12
by: Rajesh S R | last post by:
Can anyone tell me what is the difference between undefined behavior and unspecified behavior? Though I've read what is given about them, in ISO standards, I'm still not able to get the...
160
by: DiAvOl | last post by:
Hello everyone, Please take a look at the following code: #include <stdio.h> typedef struct person { char name; int age; } Person;
33
by: coolguyaroundyou | last post by:
Will the following statement invoke undefined behavior : a^=b,b^=a,a^=b ; given that a and b are of int-type ?? Be cautious, I have not written a^=b^=a^=b ; which, of course, is undefined....
12
by: Yesurbius | last post by:
'm not 100% sure what question I should ask - as I'm too sure on the best way to do this .. so let me describe what I'm trying to do (using a simplified example) and we'll go from there. You have...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.