C - 通过funcptr调用函数,为什么它不起作用?

时间:2011-06-18 21:00:29

标签: c function pointers

我有以下代码:

void print(const char* str){
      system_call(4,1,str,strlen(str)); }

void foo2(void){ print("goo \n");}


void buz(void){ ...}

int main(){
char buf[256];
    void (*func_ptr)(void)=(void(*)(void))buf;
    memcpy(buf,foo2, ((void*)buz)-((void*)foo2));
    func_ptr();
    return 0;
}

问题是,为什么这个代码会掉线?

答案是,关于调用函数而不是通过指针的东西是相对地址,但我还没弄清楚这里有什么问题?哪一行是有问题的?

谢谢你的帮助

3 个答案:

答案 0 :(得分:3)

首先,没有任何内容表明foo2()和buz()必须在内存中彼此相邻。另一方面,正如您所猜测的那样,代码必须是相对于像这样的特技工作的相对代码。但最重要的是,标准不允许这样做。

正如Chris Luts所提到的,堆栈(自动)变量在许多操作系统上都不可执行,以防止攻击。

答案 1 :(得分:2)

main()函数中的前两行是有问题的。

第1行。(void(*)(void))buf 将buf转换为函数指针是未定义的

第2行。((void*)buz)-((void*)foo2) 除非指针指向同一个数组,否则指针的减法是未定义的。

此外,Section 5.8 Functions的{​​{1}}说“虽然指向函数的指针通常被认为是内存中函数代码的地址,但在某些计算机上,函数指针实际指向一个块调用函数所需的信息。“

答案 2 :(得分:1)

首先,C函数指针机制用于等签名函数调用抽象。如果没有这些特技,这是非常强大且容易出错的。

我无法看到尝试将代码从一个地方复制到另一个地方的优势/意义。正如一些人所评论的那样,在C函数中判断相对性/可重新定位代码的数量并不容易。

您尝试将函数的代码复制到数据存储区域。一些微控制器会告诉你“嗡嗡声!”。在具有数据/程序分离存储器的机器体系结构上,给定非常理解的编译器(或识别数据/代码修饰符/属性的编译器),它将编译为特定的代码数据移动指令。接缝它会起作用......但是,即使在数据/代码分离的内存中,也不可能执行数据存储器指令。

另一方面,在“普通”数据/代码共享存储器PC中,可能它也不起作用,因为在处理器的MMU上(由加载器)声明了数据/代码段。根据处理器和操作系统的不同,尝试在数据段上运行代码是一种分段错误。