动态函数生成 [英] Dynamic function generation

查看:72
本文介绍了动态函数生成的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

亲爱的清单,


我正在尝试动态生成函数;似乎我真正想要的东西超出了C本身,但我想在这里得到确认。


在下面的最小例子中,我''想要创建内容,以便将f指向的地址放在
。特别是,我想避免/替换

memcpy行。


可能的应用程序(灵感来自Paul Graham,ANSI Common Lisp) ,

第2页):编写一个带n的函数,并返回一个函数

,将n加到其参数上。


任何评论都会非常感激。


谢谢,

Marco

//开始代码

#include< stdio.h>


int main(void){

int(* f)(const char * f,.. 。);

int n;

f = printf;

n = sizeof(int(*)(const char *,...)) ;

f(嗨!我的大小是%d。\ n,n);

f =(int(*)(const char * f,.. 。))malloc(n + 1);

memcpy(f,printf,n + 1);

if(f ==(int(*)(const char) *,...))NULL)

printf(Mem full!\ n);

f(" Hello,World!");

免费(f);

返回0;

}

//结束代码

Dear list,

I''m trying to dynamically generate functions; it seems that what I
really want is beyond C itself, but I''d like to be confirmed here.

In the minimal example below, I''d like to create content to put at
the address pointed to by f. In particular, I''d like to avoid/replace
the memcpy line.

Possible application (inspired by Paul Graham, "ANSI Common Lisp",
page 2): write a function that takes a number n, and returns a function
that adds n to its argument.

Any comments would be much appreciated.

Thanks,
Marco
// BEGIN CODE
#include <stdio.h>

int main(void) {
int (*f)(const char *f, ...);
int n;
f = printf;
n = sizeof(int(*)(const char *, ...));
f("Hi! My size is %d.\n", n);
f = (int(*)(const char *f, ...))malloc(n+1);
memcpy(f, printf, n+1);
if (f == (int(*)(const char*, ...))NULL)
printf("Mem full!\n");
f("Hello, World!");
free(f);
return 0;
}
// END CODE

推荐答案

" Marco Loskamp" <毫安*** @ math.tu-clausthal.de>在消息中写道


< snip>
"Marco Loskamp" <ma***@math.tu-clausthal.de> wrote in message

<snip>
#include< stdio.h>


#include< stdlib.h> / * malloc * /

#include< string.h> / * memcpy * /

int main(void){
int(* f)(const char * f,...);
int n;
f = printf;
n = sizeof(int(*)(const char *,...));
f(嗨!我的大小是%d。\ n,n) ;
f =(int(*)(const char * f,...))malloc(n + 1);
memcpy(f,printf,n + 1);
if (f ==(int(*)(const char *,...))NULL)
printf(Mem full!\ n);
f(Hello,World! ");


嗯..你不能指望这个工作,因为堆可能是不可执行的
。虽然没有夹板错误(见下文)。

免费(f);
返回0;
}
#include <stdio.h>
#include <stdlib.h> /*malloc */
#include <string.h> /*memcpy */
int main(void) {
int (*f)(const char *f, ...);
int n;
f = printf;
n = sizeof(int(*)(const char *, ...));
f("Hi! My size is %d.\n", n);
f = (int(*)(const char *f, ...))malloc(n+1);
memcpy(f, printf, n+1);
if (f == (int(*)(const char*, ...))NULL)
printf("Mem full!\n");
f("Hello, World!");
Hmm.. you cannot expect this to work, because the heap may
be non-executable. No splint errors though (see below).
free(f);
return 0;
}




C:\ Temp>夹板test.c

Splint 3.0.1.6 --- 2002年2月11日


test.c :(在函数main中)

test.c(9,3):将size_t赋值给int:

n = sizeof([function(char *,...)return int] *)

要允许任意整数类型匹配任何整数类型,请使用

+ matchanyintegral。

test.c(10,3):返回值(类型int)忽略:f(嗨!我的大小我......

函数调用返回的结果未被使用。如果是这样,可以

施放

导致(void)消除消息。(使用-retvalint禁止

警告)

test.c(11,42):函数malloc期望arg 1为size_t得到int:n +

1

test.c(11,35):从函数指针类型转换([function(char * ,. ..)

返回

int] *)到非函数指针(void *):

([fu] nction(char *,...)返回int] *)malloc(n + 1)

指向函数的指针被强制转换为(或用作)指向void的指针(或


$ b $反之亦然)。 (使用-castfcnptr来禁止警告)

test.c(12,10):函数memcpy期望arg 1为void *获取[function

(char

*,...)返回int] *:f

类型不兼容。 (使用-type来禁止警告)

test.c(12,13):函数memcpy期望arg 2为void *获取[function

(char

*,...)返回int]:printf

test.c(12,21):函数memcpy期望arg 3为size_t得到int:n +

1

test.c(12,10):可能空存储f作为非空参数传递:

memcpy(f,...)

可能为空的指针作为参数传递,对应于

正式

参数,没有/ * @ null @ * / annotation。如果此

参数可以使用NULL,则在函数参数

声明中添加/ * @ null @ * / annotation。

(使用-nullpass来禁止警告)

test.c(11,3):存储f可能变为空

test.c(15,3):返回值(类型int)忽略:f(Hello,World!)

test.c(16,8):函数自由期望arg 1为void *得到[function

(char *,

...)返回int] *:f


完成检查--- 10个代码警告


-

Tor< torust AT online DOT no>



C:\Temp>splint test.c
Splint 3.0.1.6 --- 11 Feb 2002

test.c: (in function main)
test.c(9,3): Assignment of size_t to int:
n = sizeof([function (char *, ...) returns int] *)
To allow arbitrary integral types to match any integral type, use
+matchanyintegral.
test.c(10,3): Return value (type int) ignored: f("Hi! My size i...
Result returned by function call is not used. If this is intended, can
cast
result to (void) to eliminate message. (Use -retvalint to inhibit
warning)
test.c(11,42): Function malloc expects arg 1 to be size_t gets int: n +
1
test.c(11,35): Cast from function pointer type ([function (char *, ...)
returns
int] *) to non-function pointer (void *):
([function (char *, ...) returns int] *)malloc(n + 1)
A pointer to a function is cast to (or used as) a pointer to void (or
vice
versa). (Use -castfcnptr to inhibit warning)
test.c(12,10): Function memcpy expects arg 1 to be void * gets [function
(char
*, ...) returns int] *: f
Types are incompatible. (Use -type to inhibit warning)
test.c(12,13): Function memcpy expects arg 2 to be void * gets [function
(char
*, ...) returns int]: printf
test.c(12,21): Function memcpy expects arg 3 to be size_t gets int: n +
1
test.c(12,10): Possibly null storage f passed as non-null param:
memcpy (f, ...)
A possibly null pointer is passed as a parameter corresponding to a
formal
parameter with no /*@null@*/ annotation. If NULL may be used for this
parameter, add a /*@null@*/ annotation to the function parameter
declaration.
(Use -nullpass to inhibit warning)
test.c(11,3): Storage f may become null
test.c(15,3): Return value (type int) ignored: f("Hello, World!")
test.c(16,8): Function free expects arg 1 to be void * gets [function
(char *,
...) returns int] *: f

Finished checking --- 10 code warnings

--
Tor <torust AT online DOT no>


2005年3月20日星期日23:59:43 +0000(UTC),Marco Loskamp

< ma *** @ math.tu-clausthal.de>写道:
On Sun, 20 Mar 2005 23:59:43 +0000 (UTC), Marco Loskamp
<ma***@math.tu-clausthal.de> wrote:
亲爱的清单,

我正在尝试动态生成函数;似乎我真正想要的不仅仅是C本身,但我想在这里得到确认。

在下面的最小例子中,我想创建内容到把...放在
可能的应用程序(灵感来自Paul Graham,ANSI Common Lisp,
第2页) :编写一个带有数字n的函数,并返回一个函数
,它将n添加到其参数中。


本练习不需要你在下面尝试的任何内容。

任何评论都会非常感激。

谢谢,
Marco

//开始代码
#include< stdio.h>

int main(void){
int(* f )(const char * f,...);
int n;
f = printf;
n = sizeof(int(*)(const char *,...));


n包含指针的大小,而不是函数的大小。我不知道有什么便携的方法可以获得函数的大小。

f(嗨!我的大小是%d。\ n, N);


计划看到四个或八个。

f =(int(*)(const char * f,...))malloc(n + 1) ;


我想知道是否向函数指针输入void *是合法的。如果是这样,

你现在有一个指针加一个字符的空间。

memcpy(f,printf,n + 1);


这会将printf的前n + 1个字节复制到你分配的空间,

可能是五或九。我很确定这不是printf的完整代码。

if(f ==(int(*)(const char *,...)) NULL)


由于您已经尝试访问内存,因此有点晚了。你需要把这个放在memcpy之前。

printf(Mem full!\ n);
f(Hello,World! ");


为什么在你知道它为NULL之后你会继续取消引用f。

你需要绕过memcpy这一次你的if评估为

true。


我的系统不区分代码地址和

数据地址。我怀疑这个假设是否非常便携。

免费(f);
返回0;
}
Dear list,

I''m trying to dynamically generate functions; it seems that what I
really want is beyond C itself, but I''d like to be confirmed here.

In the minimal example below, I''d like to create content to put at
the address pointed to by f. In particular, I''d like to avoid/replace
the memcpy line.

Possible application (inspired by Paul Graham, "ANSI Common Lisp",
page 2): write a function that takes a number n, and returns a function
that adds n to its argument.
This exercise does not require anything like what you attempt below.

Any comments would be much appreciated.

Thanks,
Marco
// BEGIN CODE
#include <stdio.h>

int main(void) {
int (*f)(const char *f, ...);
int n;
f = printf;
n = sizeof(int(*)(const char *, ...));
n contains the size of the pointer, not the size of the function. I
don''t know of any portable way to obtain the size of a function.
f("Hi! My size is %d.\n", n);
Plan on seeing four or eight.
f = (int(*)(const char *f, ...))malloc(n+1);
I wonder if casting a void* to a function pointer is legal. If so,
you now have space for a pointer plus one char.
memcpy(f, printf, n+1);
This will copy the first n+1 bytes of printf to your allocated space,
probably five or nine. I am pretty certain that this is not the
complete code for printf.
if (f == (int(*)(const char*, ...))NULL)
This is a bit late since you already tried to access the memory. You
need to place this before the memcpy.
printf("Mem full!\n");
f("Hello, World!");
Why would you continue to dereference f after you know it is NULL.
You need to bypass both the memcpy and this once your if evaluates to
true.

My system does not differentiate between the address of code and the
address of data. I doubt if this assumption is very portable.
free(f);
return 0;
}




<<删除电子邮件的del>>



<<Remove the del for email>>


在文章< sl ****************** @ pascal.math.tu-clausthal.de>,

Marco Loskamp< lo ***** @ math.wisc.edu>写道:

:我正在尝试动态生成函数;似乎我想要的只是C本身,但我想在这里得到确认。


C没有固有的机制生成一个新函数。

它不能确定任何类型的运行时编译器或

汇编器或链接器都可用,当然不提供

再次保证您将能够创建新的可执行代码 -

对于存在将

代码刻录到ROM中的环境而言,它被认为是可接受的,或代码为

的环境,标记为只读+执行,并且所有可写页面都标记为

as-not-execute。


人们可以开始考虑各种黑客附加一个

的数据到一个函数(一个''封闭''),但是一个仍然可以运行

C不提供生成新功能的方法的问题

on demand。最接近的将是

提供稳定的功能。例如,


#define gfn(n)

#define gf(n)int gfn(n)(int i){return i + const_tab [ n]);

#define MaxFunc 3219

int nextfunc = 0;

int const_tab [MaxFunc];

gf(0)

gf(1)

gf(2)

gf(3)

gf (4)

....

gf(3218)

int *()fp [MaxFunc] = {

gfn(0),gfn(1),gfn(2),gfn(3),... gfn(3218)

};


int *()genadd(int n){

if(nextfunc> = MaxFunc)返回NULL;

const_tab [nextfunc] = n;

返回fp [nextfunc ++];

}


这将(一旦调试)返回指向函数的指针,

,但最多返回3219这样的函数。

(为什么3219?为什么不呢??一个神奇的数字是一个神奇的数字。)

如果你需要更多的概括,但仍然可以使用具有有限数量功能的

问题,那么什么可以

传入生成器可能是一个字符串,描述了操作的
,返回的函数可以解析并对相应的字符串执行

操作。为了提高效率,一个

可以创建一个工作树。操作和节点[每次解析时保存
],并且在调用函数时可以处理相应的树



- -

''Walter所说的简短版本是你问了一个问题

哪个没有实用答案,请重新考虑一下
的性质
你想解决的问题"。'' - Tony Mantler
In article <sl******************@pascal.math.tu-clausthal.de>,
Marco Loskamp <lo*****@math.wisc.edu> wrote:
:I''m trying to dynamically generate functions; it seems that what I
:really want is beyond C itself, but I''d like to be confirmed here.

C has no inherent mechanism for generating a new function.
It offers no certainty that any kind of run-time compiler or
assembler or linker will be available, and certainly offers no
reassurance that you will be able to create new executable code --
it is considered acceptable for there to be environments in which the
code is burned into ROM, or environments in which the code is
marked as read+execute only, and that all writable pages are marked
as do-not-execute.

One can start thinking of all kinds of hacks to attach a piece
of data to a function (a ''closure''), but one still runs across
the problem that C does not offer ways of generating new functions
on demand. The closest one would be able to get would be to
offer a "stable" of functions. For example,

#define gfn(n)
#define gf(n) int gfn(n) ( int i ) { return i + const_tab[n] );
#define MaxFunc 3219
int nextfunc = 0;
int const_tab[MaxFunc];
gf(0)
gf(1)
gf(2)
gf(3)
gf(4)
....
gf(3218)
int *()fp[MaxFunc] = {
gfn(0), gfn(1), gfn(2), gfn(3), ... gfn(3218)
};

int *() genadd( int n ) {
if ( nextfunc >= MaxFunc ) return NULL;
const_tab[nextfunc] = n;
return fp[nextfunc++];
}

This will (once debugged) return a pointer to a function as requested,
but has a maximum limit of 3219 such functions returned.
(Why 3219? Why not!? A magic number is a magic number.)
If you need more generalization, but can still live with the
issue of having a limited number of functions, then what could
be passed in to the generator could be a string that described
the operations, and the function returned could parse and take
action on the appropriate string. For more efficiency, one
could create a "work tree" of operations and nodes [saves
on parsing each time], and the appropriate tree could be processed
when the function was invoked.
--
''The short version of what Walter said is "You have asked a question
which has no useful answer, please reconsider the nature of the
problem you wish to solve".'' -- Tony Mantler


这篇关于动态函数生成的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆