帮忙说明下错误原因

mkworld 2011-12-12 11:41:05

#include<stdio.h>
void function(void){
printf("Hello Function!\n");
}
int main(void){
char fake_function[1000]; int i;
void *func_pointer;
printf("函数指针实行"); getchar();
func_pointer=(void *)function;
((void (*)(void))func_pointer)(); // 函数输出
printf("复制并运行数组变量?"); getchar();
for(i=0;i<1000;i++){ fake_function[i]=((char *)(function))[i]; }
func_pointer=(void *)fake_function;
((void (*)(void))func_pointer)(); // 函数输出
return 0;
}

Segmentation fault
帮忙分析下错误原因
...全文
118 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
cup_t 2011-12-13
  • 打赏
  • 举报
回复
代码是具有艺术性的,而你这。。。
AnYidan 2011-12-13
  • 打赏
  • 举报
回复
google 函数指针的用法
tag180 2011-12-13
  • 打赏
  • 举报
回复
楼主指针玩来玩去 结果 Segmentation fault 了~别在不需要的地方搞这么高科技的。。咱是用语言解决问题,不是用语言引入问题。。。看了半天晕乎了,,,帮顶吧
gkf57908 2011-12-13
  • 打赏
  • 举报
回复
函数指针不是这么玩的,给分
didijiji 2011-12-13
  • 打赏
  • 举报
回复
代码应该写的工整一点。
狂且 2011-12-13
  • 打赏
  • 举报
回复
你这个函数指针和通用指针来回转有什么用么?

表示看糊涂了.....嘿嘿......

帮顶吧.
iamnobody 2011-12-13
  • 打赏
  • 举报
回复
不要耍指针,否则你会被指针耍得很惨。。
yulinlang 2011-12-13
  • 打赏
  • 举报
回复
贴个gdb调试过程分析分析:
在21行设断点并运行程序:
(gdb) break 21
Breakpoint 1 at 0x40142c: file csdn81.c, line 21.
(gdb) run
Starting program: d:\wenwen\a.exe
[New Thread 1356.0x4f4]
函数指针实行
Hello Function!
复制并运行数组变量?

Breakpoint 1, main () at csdn81.c:21
warning: Source file is more recent than executable.
21 func_pointer=(void *)fake_function;


(gdb) p function
$1 = {void (void)} 0x40138c <function>
这里可以看到函数function地址在0x40138c处。

(gdb) p func_pointer
$2 = (void *) 0x28fb38
func_pointer值为0x28fb38,也就是fake_function数组在0x28fb38处。

反汇编function代码:
(gdb) disas 0x40138c
Dump of assembler code for function function:
0x0040138c <+0>: sub $0x1c,%esp
0x0040138f <+3>: movl $0x403064,(%esp)
0x00401396 <+10>: call 0x401b8c <puts>
0x0040139b <+15>: add $0x1c,%esp
0x0040139e <+18>: ret
End of assembler dump.

反汇编数组fake_function处代码:
(gdb) x/5i 0x28fb38
0x28fb38: sub $0x1c,%esp
0x28fb3b: movl $0x403064,(%esp)
0x28fb42: call 0x290338
0x28fb47: add $0x1c,%esp
0x28fb4a: ret
两段代码的call地址出现不同。

看一下指令情况,function的(头16字节):
(gdb) x/16xb 0x40138c
0x40138c <function>: 0x83 0xec 0x1c 0xc7 0x04 0x24 0x64
0x30
0x401394 <function+8>: 0x40 0x00 0xe8 0xf1 0x07 0x00 0x00
0x83
fake_function的(头16字节):
(gdb) x/16xb 0x28fb38
0x28fb38: 0x83 0xec 0x1c 0xc7 0x04 0x24 0x64 0x30
0x28fb40: 0x40 0x00 0xe8 0xf1 0x07 0x00 0x00 0x83

问题出在0xe8 0xf1 0x07 0x00 0x00这个call指令处,查询Intel指令集手册
E8 cd CALL rel32 相对近调用,位移量相对于下一条指令。
此处编译器生成相对近调用,因此用
((void (*)(void))func_pointer)();
调用函数时,并未调用0x401b8c处的puts,而是去跳转去了0x290338处,而此处指令是未知的,所以程序崩溃。

假如编译器在这里使用绝对地址调用的话,那么程序可以正常执行,但是编译器生成什么样的指令是没有保证的,换用不同的编译器可能会成功,但这种玩弄指针的行为是危险的。

69,336

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧