背景:
阅读文章

MUD游戏一个引起当机的BUG的讨论

[日期:2021-04-07] 来源:niub.net之mud制作讨论组   作者:jackyboy [字体: ]

在我自己的环境上,我编写下面的命令代码,运行后自己即刻断线,然后在第一个call_out
未调用前自己再次上线,再次执行改命令,在第一个call_out到达时间开始执行时,将会因
为me的值由object变为0导致MUDOS的段失败崩溃。如果运行两次命令不会当,可以多运行几
次看看。在我自己的OS + LIB里这个问题似乎是屡试屡“爽”,但是我不能100%肯定,所以
贴出来请大家也试试看。我用的是v22.2b11版本。

int main(object me,string arg)
{
        string out="";
        if(!arg)
                arg="1234567890";
        for(int i=0;i<3;i++)
                out+=arg;
        //remove_call_out("do_out");
        call_out("do_out",10,me,out);
        destruct(me);
        return 1;
}

void do_out(object me,string out)
{
        tell_object(me,out);


以下是关于解决途径的讨论,可以参考下goodtaste关于MudOS中call_out的讲解
 
作者:Super  发表时间:2001年7月31日 13:15 
--------------------------------------------------------------------------------

确实有这个BUG。
我看了一下mudos,发现里面的在destruct_objetct()时,并没有消除call_out。
不过只要把simulate.c里面的destruct_object()里面最后加一句
remove_all_callout(ob);
应该就能解决问题了,呵呵。


作者:goodtaste  发表时间:2001年8月1日 19:10 
--------------------------------------------------------------------------------

你说的那个方法有效么?我看了看v22pre11的代码,
感觉不对阿。

这里被destruct 的是call_out调用的函数里使用到
的对象,而不是发起call_out时候的current_object。
在efuns_main.c的f_call_out这个efun里,传递给
new_call_out的第一个参数是current_object,也就是
调用call_out这个efun的物件,这里就是这个命令。
new_call_out将这个对象存入一个pending_call_t
的结构中,然后将这个结构放进一个数组里。
而remove_all_call_out()的唯一参数就是一个object_t
他的做法是把整个结构数组遍历一遍,如果发现某个
元素(是一个pending_call_t结构)中的ob是remove_all_call_out
的参数,那么就把这个call_out去掉。所以在destruct调
user_ob之前调用remove....所传递过去的参数user_ob是没有用的,
他查找不到你所希望去掉的那个call_out。


作者:Super  发表时间:2001年8月1日 19:46 
--------------------------------------------------------------------------------

确实。。
我那样做是徒劳无功的,都怪当时没有看仔细:P
现在重新看了一遍,发现在new_call_out()里面
有一句cop->ob = ob这里的OB是call_out的发起者。

恩,这么说来,那个问题就完完全全是代码的问题了。呵呵。。

以下是由这个问题引发的代码效率的讨论

作者:darks  发表时间:2001年7月31日 15:49 
--------------------------------------------------------------------------------

所以es为 char 增加一个start_call_out 来处理这个问题
作为一个call_out本身 他不应该在me这个对象不存在的时候 取消call_out
这不符合这个函数的原则 这个函数的原意就是延时呼叫
参数传递以后 应该做新的判断
就好像 x/0 这不能作为bug来处理 我是这么认为的
我更喜欢说 嗨 jackyboy 你写了这个代码会出错的 :)


作者:doing  发表时间:2001年7月31日 19:36 
--------------------------------------------------------------------------------

所以es为 char 增加一个start_call_out 来处理这个问题
作为一个call_out本身 他不应该在me这个对象不存在的时候 取消call_out

其实 start_call_out 并不在于这个目的。事实上即使是 ob 自身呼叫的顶时器,在
析构的时候也不会自动清除 call_out 的。

而且 es 里面的 start_call_out 几乎可以说就是一个 bug,没有任何用处。因为如果
定时器发起者调用 ob 的 start_call_out,但是如果在定时器呼叫前发起者就被析构了
的话,结果该定时器也无法执行 -- 因为定时器中的函数 owner 被析构了。如果需要使
用这个功能,必须用 bind。

这不符合这个函数的原则 这个函数的原意就是延时呼叫
参数传递以后 应该做新的判断
就好像 x/0 这不能作为bug来处理 我是这么认为的
我更喜欢说 嗨 jackyboy 你写了这个代码会出错的 :)

代码当然是错的,但是不能搞得系统当机呢,否则说明系统有问题啊。 

 

作者:find  发表时间:2001年7月31日 21:10 
--------------------------------------------------------------------------------

在 es2 系统里 tell_object 好像是一个 simul efun,
再此函数里做个检查就是了,但 tell_object 函数使用频率过高,
这会降低执行效率。
这其实就象是 C 和 BASIC,C 把责任交给程序员,C 不做严格的
检查,你的代码有问题他也一样执行,出问题就挂,这有机高的效
率。BASIC 有严格的检查机制,分担了程序员的责任,但是效率
极其低下。
要成为一个高效的系统,就要尽量减少 MudOS 和 LIB 底层的检查
机制,同时严格把关,提高代码质量。要不就加大检查力度,但效
率的代价是必须要负的 

收藏 推荐 打印 | 录入:sbso | 阅读:
本文评论   [发表评论]   全部评论 (0)
内容推送
52mud提供
一起回忆泥巴游戏QQ群68186072
52mud官方微信公众平台
热门评论