我正在研究内存处理,我遇到了这段代码:
void print(const char * str){
printf(str);
}
void (*print_ptr)(const char *)=print;
void foo2(void){
print("goo\n");
return;
}
void baz(void){
print("foo\n");
return;
}
int main()
{
char buf[256];
void (*func_ptr)(void)=(void (*)(void))buf;
memcpy(buf,foo2,((void *)baz)-((void *) foo2));
func_ptr();
return 0;
}
此代码将导致seg fault到达
func_ptr();
我不明白为什么。如果我将指针更改为指向静态函数(如func_ptr=&baz
它将正常工作,但动态代码不会。)
根据我的理解,代码本身将被复制到堆栈中,应该是它
这段代码有什么问题?
答案 0 :(得分:4)
您要做的是将包含foo2()
的对象代码复制到缓冲区并执行它。由于以下几个原因,这不会起作用:
您的代码被复制到buf
,这将被分配在数据空间中,这是不可执行的(即内存管理器不会在该内存区域设置执行权限)。
在一般情况下,代码不太可能重定位。它可能包含对自身的绝对引用,也可能包含对其余代码的相对引用,这两种代码都会在复制时中断。
您无法保证代码将按照给定的顺序使用函数进行编译,因此无法保证您只复制foo2()
。实际上,无法保证编译器会将foo2()
生成为单个连续的二进制blob。其中一部分可能(例如)在bar()
之后。或者(相对常见的情况)函数的部分可能在入口点之前。
如果您真的想了解它为什么会中断,请使用buf
为mmap()
和MAP_ANON
分配PROT_READ|PROT_WRITE|PROT_EXEC
的内存来修复(1) ,然后在gdb
下运行它。我建议使用-O0
进行编译(禁用优化)以最大限度地提高某些工作的可能性,但我会重申你没有任何保证。
更大的问题是为什么你要复制代码的原因。