Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > Call function address stored in type of size_t?

Reply
Thread Tools

Call function address stored in type of size_t?

 
 
Adam Warner
Guest
Posts: n/a
 
      12-22-2004
Hello all,

I'm very new to C but I have a number of years of Common Lisp programming
experience. I'm trying to figure out ways of translating higher order
concepts such as closures into C. The code will not be idiomatic C.

GCC has an extension to ISO C that permits nested functions:
<http://gcc.gnu.org/onlinedocs/gcc/Nested-Functions.html>

For implementing closures they have a serious limitation:

If you try to call the nested function through its address after the
containing function has exited, all hell will break loose. If you try
to call it after a containing scope level has exited, and if it refers
to some of the variables that are no longer in scope, you may be lucky,
but it's not wise to take the risk. If, however, the nested function
does not refer to anything that has gone out of scope, you should be
safe.

I'm hopeful that if I heap allocate all closed over variables that I will
simulate closures. I'm aware of the distaste some have for the extension:
<http://groups.google.co.nz/groups?selm=1V6uS-Id-23%40gated-at.bofh.it>

At this stage my question is elementary: How do I make all hell break
loose in the code below?

#include <stdio.h>

size_t glfn1() {
int x=1;
int inc() {
return printf("%d\n",x=x+1);
}
return (size_t) &inc;
}

int main() {
size_t fn_address=glfn1();
/* All hell will break loose */
fn_address();
return 0;
}

I understand size_t is the ideal type for storing a pointer because it
will also work upon 64-bit platforms that have 32-bit ints.

How do I induce the compiler to accept the address of the function inc as
a function type? The called object of type size_t is not a function type.

Regards,
Adam
 
Reply With Quote
 
 
 
 
Charlie Gordon
Guest
Posts: n/a
 
      12-22-2004
"Adam Warner" <(E-Mail Removed)> wrote in message
news(E-Mail Removed) .nz...
> Hello all,
>
> I'm very new to C but I have a number of years of Common Lisp programming
> experience. I'm trying to figure out ways of translating higher order
> concepts such as closures into C. The code will not be idiomatic C.
>
> GCC has an extension to ISO C that permits nested functions:
> <http://gcc.gnu.org/onlinedocs/gcc/Nested-Functions.html>


Of course this question is off topic here, ask on a gcc forum.

> For implementing closures they have a serious limitation:
>
> If you try to call the nested function through its address after the
> containing function has exited, all hell will break loose. If you try
> to call it after a containing scope level has exited, and if it refers
> to some of the variables that are no longer in scope, you may be lucky,
> but it's not wise to take the risk. If, however, the nested function
> does not refer to anything that has gone out of scope, you should be
> safe.
>
> I'm hopeful that if I heap allocate all closed over variables that I will
> simulate closures. I'm aware of the distaste some have for the extension:
> <http://groups.google.co.nz/groups?selm=1V6uS-Id-23%40gated-at.bofh.it>


No, that won't work.
You can simulate closures with allocation by storing all variables referred to
by your function in a structure, and refer to structure members instead of
global identifiers, but that is not what you really want, and C++ will provide
the syntactical sugar to make it more appealing to you (but more distasteful to
most of us).

> At this stage my question is elementary: How do I make all hell break
> loose in the code below?
>
> #include <stdio.h>
>
> size_t glfn1() {
> int x=1;
> int inc() {
> return printf("%d\n",x=x+1);
> }
> return (size_t) &inc;
> }


easy: the function inc() increments a location on the stack relative to a frame
pointer passed as an implicit argument. The gcc implementation generates code
dynamically on the stack upon entering glfn1() consisting of a register
assignment to the frame pointer and a jump to the code for glfn1. This is
called a trampoline thunk. &inc points indeed to automatic storage in the glfn1
activation. dereferencing this pointer after glfn1 returns may well crash !
if not, who knowns what location will be changed by inc() ?

> int main() {
> size_t fn_address=glfn1();
> /* All hell will break loose */
> fn_address();
> return 0;
> }
>
> I understand size_t is the ideal type for storing a pointer because it
> will also work upon 64-bit platforms that have 32-bit ints.


This is not a good assumption. intptr_t is the type you are referring to, but
that will not solve your problem.

> How do I induce the compiler to accept the address of the function inc as
> a function type? The called object of type size_t is not a function type.


with a cast:

(*(size_t(*)())fn_address)();

but again, this will not suffice for your closure to stand.

--
Chqrlie.


 
Reply With Quote
 
 
 
 
Gordon Burditt
Guest
Posts: n/a
 
      12-22-2004
>I understand size_t is the ideal type for storing a pointer because it
>will also work upon 64-bit platforms that have 32-bit ints.


Why will it work for storing a FUNCTION pointer? If a function pointer
takes more bits than a size_t, you have trouble.

Data Pointer Code Pointer MS-DOS Model Name Works?
16 bits 16 bits small yes
32 bits 16 bits compact? yes
16 bits 32 bits middle? NO!
32 bits 32 bits large yes
64 bits 32 bits humongous yes
32 bits 64 bits gigantic NO!
64 bits 64 bits intergalactic yes

>How do I induce the compiler to accept the address of the function inc as
>a function type? The called object of type size_t is not a function type.


If ugly casts or assignment to a variable of type
pointer-to-function-returning-crap don't work, consider memmove()
between a size_t and such a function pointer. If you're going to
invoke undefined behavior anyway, this probably won't make it that
much worse.

Gordon L. Burditt
 
Reply With Quote
 
CBFalconer
Guest
Posts: n/a
 
      12-22-2004
Adam Warner wrote:
>
> I'm very new to C but I have a number of years of Common Lisp
> programming experience. I'm trying to figure out ways of
> translating higher order concepts such as closures into C. The
> code will not be idiomatic C.
>
> GCC has an extension to ISO C that permits nested functions:
> <http://gcc.gnu.org/onlinedocs/gcc/Nested-Functions.html>


You cannot nest functions in ISO standard C (the only form
discussed here). Any non-standard C is, by definition,
non-portable and off-topic on c.l.c. You can get some of the
effects by suitable break-up into files, and still have standard
C. Such a discussion would be on-topic.

If you really want nested functions use a language whose ISO
standard supports them. Pascal, Extended Pascal, and Ada all come
to mind.

--
Chuck F ((E-Mail Removed)) ((E-Mail Removed))
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net> USE worldnet address!


 
Reply With Quote
 
Charlie Gordon
Guest
Posts: n/a
 
      12-22-2004
"Gordon Burditt" <(E-Mail Removed)> wrote in message
news:cqaph8$(E-Mail Removed)...
> >I understand size_t is the ideal type for storing a pointer because it
> >will also work upon 64-bit platforms that have 32-bit ints.

>
> Why will it work for storing a FUNCTION pointer? If a function pointer
> takes more bits than a size_t, you have trouble.
>
> Data Pointer Code Pointer MS-DOS Model Name Works?
> 16 bits 16 bits small yes
> 32 bits 16 bits compact? yes
> 16 bits 32 bits middle? NO!
> 32 bits 32 bits large yes
> 64 bits 32 bits humongous yes
> 32 bits 64 bits gigantic NO!
> 64 bits 64 bits intergalactic yes


Let's all have a thought for Gary Kildall who died ten years ago.
He was the creator of CP/M and the GEM Desktop GUI.
He was famed for having taken the most expensive vacation of all time in 1980,
but that is a legend.
His contribution to the PC industry is quite amazing, but he wasn't recognized
until after his death of uncertain causes.
Read all about him on : http://en.wikipedia.org/wiki/Gary_Kildall
Incidentally, a lesser known fact connects him to this OT post :
His company Digital Research, Inc. was originally named "Intergalactic Digital
Research"

> >How do I induce the compiler to accept the address of the function inc as
> >a function type? The called object of type size_t is not a function type.

>
> If ugly casts or assignment to a variable of type
> pointer-to-function-returning-crap don't work, consider memmove()
> between a size_t and such a function pointer. If you're going to
> invoke undefined behavior anyway, this probably won't make it that
> much worse.


In this case memcpy() would do as well, as the objects do not overlap

--
Chqrlie.



 
Reply With Quote
 
Stephen Sprunk
Guest
Posts: n/a
 
      12-22-2004
"Adam Warner" <(E-Mail Removed)> wrote in message
news(E-Mail Removed) .nz...
> I understand size_t is the ideal type for storing a pointer because it
> will also work upon 64-bit platforms that have 32-bit ints.


There is no guarantee that size_t is large enough to hold an object pointer,
much less a function pointer.

> How do I induce the compiler to accept the address of the function
> inc as a function type? The called object of type size_t is not a
> function type.


Declare fn_address as a function pointer, of course:

size_t (*fn_address)() = glfn1();

Of course, I can't figure out the right syntax to declare glfn1() as
returning that type, but surely someone else here will know...

S

--
Stephen Sprunk "Stupid people surround themselves with smart
CCIE #3723 people. Smart people surround themselves with
K5SSS smart people who disagree with them." --Aaron Sorkin


 
Reply With Quote
 
Keith Thompson
Guest
Posts: n/a
 
      12-22-2004
Adam Warner <(E-Mail Removed)> writes:
[...]
> I understand size_t is the ideal type for storing a pointer because it
> will also work upon 64-bit platforms that have 32-bit ints.


No, a pointer type is the ideal type for storing a pointer. In
particular, a function pointer type is the ideal type for storing a
pointer to a function.

> How do I induce the compiler to accept the address of the function inc as
> a function type? The called object of type size_t is not a function type.


Here's a version of your program using the correct type for the
function pointer. (I've also un-nested the inc function, since
standard C doesn't support nested functions.)

#include <stdio.h>

typedef int (*func_ptr)(void);

int x = 1;

int inc(void)
{
return printf("%d\n", x++);
}

func_ptr glfn1(void)
{
return inc; /* or "return &inc;" */
}

int main(void)
{
func_ptr fn_address = glfn1();
fn_address();
return 0;
}

--
Keith Thompson (The_Other_Keith) http://www.velocityreviews.com/forums/(E-Mail Removed) <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.
 
Reply With Quote
 
infobahn
Guest
Posts: n/a
 
      12-22-2004
Adam Warner wrote:

<snip>

>
> I understand size_t is the ideal type for storing a pointer because it
> will also work upon 64-bit platforms that have 32-bit ints.


The ideal type for storing a pointer to a type T is T *.

If you don't know the type of an object to which you're pointing,
you can use void *. If you don't know the type of a function to
which you're pointing, but do at least know the return type T, use
T (*)().
 
Reply With Quote
 
Adam Warner
Guest
Posts: n/a
 
      12-22-2004
Hi CBFalconer,

> You cannot nest functions in ISO standard C (the only form discussed
> here). Any non-standard C is, by definition, non-portable and off-topic
> on c.l.c.


OK. We discuss implementation-specific extensions of ANSI Common Lisp in
comp.lang.lisp so I was unaware this kind of discussion was verboten here.

> You can get some of the effects by suitable break-up into files, and
> still have standard C. Such a discussion would be on-topic.


I would love to see how this can be achieved!

Regards,
Adam
 
Reply With Quote
 
Adam Warner
Guest
Posts: n/a
 
      12-22-2004
Hi Charlie Gordon,

>> I understand size_t is the ideal type for storing a pointer because it
>> will also work upon 64-bit platforms that have 32-bit ints.

>
> This is not a good assumption. intptr_t is the type you are referring to, but
> that will not solve your problem.
>
>> How do I induce the compiler to accept the address of the function inc as
>> a function type? The called object of type size_t is not a function type.

>
> with a cast:
>
> (*(size_t(*)())fn_address)();
>
> but again, this will not suffice for your closure to stand.


And who says Lisp has too many parentheses

Many thanks for the pointers. Now having found 7.18.1.4 of C99 I see it
declares the intptr_t and uintptr_t types as optional, so even their use
appears to potentially make my code non-portable. I suspect these types
will be widely defined by implementations.

I've also discovered I have to make significant use of local variables
simply to define the order of evaluation. I've checked that, at least in
simple cases, an optimising compiler like GCC can remove these temporaries
from generated assembly when they turn out to be unnecessary.

Regards,
Adam
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
How to call function whose function call with arguments is in astring Options grbgooglefan C Programming 4 01-30-2008 05:12 PM
How to call function whose function call with arguments is in astring grbgooglefan C++ 2 01-30-2008 07:18 AM
How to call function whose function call with arguments is in astring Options grbgooglefan C Programming 0 01-30-2008 04:19 AM
cast from function call of type int to non-matching type double =?ISO-8859-1?Q?Martin_J=F8rgensen?= C Programming 16 06-19-2006 07:48 AM
write a function such that when ever i call this function in some other function .it should give me tha data type and value of calling function parameter komal C++ 6 01-25-2005 11:13 AM



Advertisments