我正在Linux上尝试使用函数指针,并尝试执行这个C程序:
#include <stdio.h>
#include <string.h>
int myfun()
{
return 42;
}
int main()
{
char data[500];
memcpy(data, myfun, sizeof(data));
int (*fun_pointer)() = (void*)data;
printf("%d\n", fun_pointer());
return 0;
}
很不幸,在调用fun_pointer()
时,它会导致段错误。我怀疑这与一些内存标志有关,但我没有找到相关信息。
您能解释一下为什么这段代码会导致段错误吗?不要看固定的data
数组大小,它是没问题的,并且在不调用该函数的情况下拷贝是成功的。
更新:最终我发现应该使用带有PROT_EXEC
标志的mprotect系统调用将内存段标记为可执行。此外,根据POSIX规范,内存段应通过mmap函数返回。
#include <stdio.h>
#include <string.h>
#include <sys/mman.h>
int myfun()
{
return 42;
}
int main()
{
size_t size = (char*)main - (char*)myfun;
char *data = mmap(NULL, size, PROT_EXEC | PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
memcpy(data, myfun, size);
int (*fun_pointer)() = (void*)data;
printf("%d\n", fun_pointer());
munmap(data, size);
return 0;
}
为确保函数中的代码位置独立,应使用-fPIC
gcc选项编译此示例。
myfun
的代码副本,因为我将这段代码复制到了data
数组中。 - Alexander Rodin-Wall -Wextra -pedantic
),然后修复这些警告。发布的代码会发出一整串警告。 - user3629249