Jack 发表于 2010-8-3 18:18:39

asio示例代码的一个bug.

本帖最后由 Jack 于 2010-8-3 18:22 编辑

完整代码:http://www.boost.org/doc/libs/1_ ... location/server.cpp
使用自定义内存分配器来分配完成键等信息.多数情况下,使用系统自定义的就够用了,但是如果效率非常高,就有必要使用.但是这个代码有一个非常隐藏的bug.在有连接的时候(也就是有session存在时),如果自然退出,就会导致访问违例...
因为handler_allocator这个对象析构后,asio_handler_allocate还会被调用,这时就会继续访问handler_allocator对象的内存,这时就会产生访问违例.
要修正这个问题也很容易:
1.不使用这个东西,因为这个东西就是分配一个完成键而已空间不大,如果效率要求不是特别特别高,完全可以不用.
2.使用单件内存池分配对象,直接custom_alloc_handler这个模板类里实现,不过得注意线程安全.(示例本身这个代码就没注意线程安全,在多线程下使用,必出问题)最好用mutex加锁下(boost的单件内存分配对象是线程安全的,无需要考虑).
3.根据asio_handler_deallocate调用规则,自己另行设计.


话说回来,这个示例只是一个示例,有bug也很正常,所以就不叫bug,但多多少少会使人误用.

Jack 发表于 2010-8-4 10:21:31

本帖最后由 Jack 于 2010-8-6 13:47 编辑

这我修正后的示例代码. 并且可以采用Half Sync/Half Async模式和Leader/Follower模式,可以看到使用asio完成这样的设计非常简单直观...

Jack 发表于 2010-8-6 18:40:18

本帖最后由 Jack 于 2010-8-6 19:01 编辑

我把我写的示例代码去掉了。因为在官方看到了临时修正这个bug的方案,如下:
修改: asio\detail\handler_alloc_helpers.hpp文件241行:

    if (pointer_)
    {
      pointer_->value_type::~value_type();
      boost_asio_handler_alloc_helpers::deallocate(
          pointer_, value_size, handler_);
      pointer_ = 0;
    }
替换为:
      if (pointer_)
      {
                handler_type local_handler_copy(handler_);
                pointer_->value_type::~value_type();
                boost_asio_handler_alloc_helpers::deallocate(
                pointer_, value_size, local_handler_copy);
                (void) local_handler_copy;
                pointer_ = 0;
      }
上面其实就是在调用pointer_->value_type::~value_type()函数之前(如果引用计数为1的话,这里实际上会引发调用session析构),将handler多拷贝了一次(增加了引用计数).
就是代码第一行代码:handler_type local_handler_copy(handler_)增加了引用计数.
估计不久,这个bug的修复,将会在正式版发布...另外,发现使用asio的人少的可怜,估计是asio没ACE有名气的原因,呵呵。。。

Jack 发表于 2010-8-17 17:55:27

boost-1.44版的asio已修复了这个问题.

iq50 发表于 2011-1-21 14:45:18

ding你,BOOST在实际工作中还是值得常用的,和你在群里说的一样,C++程序员使用BOOST更是一种趋势。ACE如果不是较大的项目,离工作好遥远。
页: [1]
查看完整版本: asio示例代码的一个bug.