C-c 设计模式

发布于 2016-11-08 11:50:00 字数 1064 浏览 1275 评论 3

a->p->attack=trans;这句错误为什么

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

typedef struct player
{
void (*attack)(void *);
}player;

player *creatplay()
{
player *p=(player *)malloc(sizeof(player));
if(p==NULL)
return NULL;
return p;
}

typedef struct foreign
{
void (*jingong)();
}foreign;

void jingong()
{
printf("进攻");
}

foreign *creatforeign()
{
foreign *f=(foreign *)malloc(sizeof(foreign));
if(f==NULL)
return NULL;
f->jingong=jingong;
return f;
}

typedef struct adapter
{
player *p;
foreign *f;
}adapter;

void trans(void *padapter)
{
((adapter *)padapter)->f->jingong();
}

adapter *creat()
{
adapter *a=(adapter *)creatplay();
a->f=creatforeign();
a->p->attack=trans;
return a;
}

int main()
{
player *p=(player *)creat();
p->attack(p);
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

虐人心 2017-10-09 05:27:44

a->p->attack=trans;
这句话的意思是 把 trans的地址给a->p-attack,
a->p-attack是一个不带入参的函数,
trans带入参 *padapter,二者不匹配,所以报错

想挽留 2017-03-23 03:23:00

这段程序很有意思, 具体问题就是 a->p 没有初始化. 下面具体看看.

为了方便, 把creat函数稍改了一下, 加入p指针

adapter *creat()
{
    player *p=(adapter *)creatplay();
    adapter *a=p;
    a->f=creatforeign();
    a->p->attack=trans;
    return a;
}

gdb可见:

(gdb) x /2 p
0x601010:       0x00000000      0x00000000
(gdb) x /4 a
0x601010:       0x00000000      0x00000000      0x00601030      0x00000000
(gdb) x /2 a->p
0x0:    Cannot access memory at address 0x0
(gdb) x /2 a->f
0x601030:       0x0040053d      0x00000000
(gdb) x jingong
0x40053d <jingong>:     0xe5894855

player *p在堆中分到一段内存0x601010, 然后被a占用了;

0x601010:       0x00000000      0x00000000

本来是要放入p->attack的, 但现在要放入的是a->p;而a->p->attack是说, 先拿a->p(指针), 为0, 然后从地址0x0处去取a->p->attack; 这个地址不能访问. 程序罢工了.

那么我们把a->p初始化一下:

adapter *creat()
{
    player *p=(adapter *)creatplay();
    adapter *a=p;
    a->p=creatplay();
    a->f=creatforeign();
    a->p->attack=trans;
    return a;
}
(gdb) x /4x a
0x601010:       0x00601030      0x00000000      0x00601050      0x00000000
(gdb) x /2x a->p
0x601030:       0x00400592      0x00000000
(gdb) x /2x trans
0x400592 <trans>:       0xe5894855      0x10ec8348

可以向下走了, 接着在main里报SF:

(gdb) n
main () at attack.c:60
60          p->attack(p);
(gdb) x /2x p
0x601010:       0x00601030      0x00000000
(gdb) n

Program received signal SIGSEGV, Segmentation fault.
0x0000000000601030 in ?? ()

这里可以看到, main里现在的这个p实际上应该是一个指针的指针... 改一下:

int main()
{
    player **p1=(player *)creat();
    player *p=*p1;
    p->attack(p);
}
(gdb) n
63          p->attack(p);
(gdb) x /2x p1
0x601010:       0x00601030      0x00000000
(gdb) x /2x p
0x601030:       0x00400592      0x00000000
(gdb) x /2x p->attack
0x400592 <trans>:       0xe5894855      0x10ec8348
(gdb) n

Program received signal SIGSEGV, Segmentation fault.
0x00000000004005a6 in trans (padapter=0x601030) at attack.c:44
44          ((adapter *)padapter)->f->jingong();

嗯, 函数trans里报SF了... 不改了, 呵呵.顺便问一下, lz这个程序是参考了什么写的啊.

晚风撩人 2017-01-27 17:26:20

gcc version 4.6.2 (SUSE Linux) 编译你贴出来的代码,没有问题。
不过会coredump,你指的有问题是这个吧?

Program terminated with signal 11, Segmentation fault.
#0 0x000000000040065a in creat () at test.c:51
51 a->p->attack=trans;
(gdb) bt
#0 0x000000000040065a in creat () at test.c:51
#1 0x0000000000400679 in main () at test.c:57
(gdb) p trans
$1 = {void (void *)} 0x40060b <trans>
(gdb) p a
$2 = (adapter *) 0x602010
(gdb) p *a
$3 = {p = 0x0, f = 0x602030}
(gdb)

core的原因是,p是一个空指针。

希望可以帮助到你。

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文