7

我们在这里处理C。我只是有这个想法,想知道是否可以访问存储函数的内存点,例如foo并将函数的内容复制到内存中的另一个点。具体来说,我试图让以下工作:

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

void foo(){
    printf("Hello World");
}

int main(){

    void (*bar)(void) = malloc(sizeof foo);
    memcpy(&bar, &foo, sizeof foo);


    bar();
    return 0;
}

但是运行它会出现总线错误:Bus error: 10. 我正在尝试将 function 的内容复制foo到内存空间中bar,然后执行新创建的 function bar

这只是为了看看这样的事情是否可能,以揭示 C 语言的复杂性。我没有考虑这有什么实际用途。

我正在寻找指导以使其正常工作,或者以其他方式被告知,原因是为什么这不起作用

编辑查看了一些答案并了解了readwriteexecutable内存,我突然意识到可以通过写入可执行内存在 C 中动态创建函数。

4

2 回答 2

8

使用标准 C,您尝试做的是实现定义的行为,并且无法移植。在给定的平台上,您也许可以完成这项工作。

给你的内存malloc通常是不可执行的。跳转到那里会导致总线错误 ( SIGBUS)。假设您在类似 POSIX 的系统上,请使用mmap和标志为函数分配内存,这些标志导致内存区域可执行或用于mprotect将区域标记为可执行。

您还需要更加小心您提供的内存量,您不能简单地获取函数的大小并期望它是函数的长度,sizeof并不是为了提供这种功能而设计的。您需要使用其他方法找出函数长度。

于 2015-11-27T20:18:57.873 回答
6

在现代桌面上,虚拟内存管理器会妨碍您。内存区域有三种访问方式:执行。在代码段只有执行权限的系统上,memcpy将因总线错误而失败。在更典型的情况下,只有代码段有执行权限,你可以复制函数,但不能运行,因为包含的内存区域bar将没有执行权限。

此外,确定函数的大小是有问题的。考虑以下程序

void foo( int *x )
{
    printf( "x:(%zu %zu) ", sizeof x, sizeof *x );
}

int main( void )
{
    int x = 0;
    foo( &x );
    printf( "foo:(%zu %zu)\n", sizeof foo, sizeof *foo );
}

在我的系统上,输出x:(8 4) foo:(1 1)表明获取sizeof函数指针或函数本身不是受支持的操作。

于 2015-11-27T20:19:59.660 回答