平台崩溃之operator new异常(三)-2010-5-14

来源:互联网 发布:java web工作原理 编辑:程序博客网 时间:2024/04/29 05:10

2010-5-14

今天上午10点左右,发现平台管理客户端不能登陆平台,远程控制平台,发现弹出first-chance exception.

问题出在添加好友通知协议(1020-通知)的以下代码

                   DB_AddFriend(pszSrcUserSeq, pszSrcOrgID, pszDestUserSeq, pszDestOrgID, pszSrcGNo);

                   异常描述为:主键重复。

                   引起主键重复的原因是:重复收到了请求。什么原因导致重复收到请求?该问题先放放,应该不是导致平台无响应问题的原因。               

 

问题2

         服务器在用ado连接mysql时,

         m_pConnection->Open(m_strConnectString.c_str(),"","",adConnectUnspecified);

         报出first-chance exceptionado抛出的_com_error异常

         e.Source() = "Microsoft OLE DB Provider for ODBC Drivers"

         e.Description()="[MySQL][ODBC 3.51 Driver]Lost connection to MySQL server at 'reading authorization packet', system error: 0"

         e.Error() = 80004005

         e.ErrorMessage() = 未指定的错误

         有时又报出:

         e.Description()="[MySQL][ODBC 3.51 Driver]Lost connection to MySQL server at 'sending authentication information', system error: 0"

        

         问题:为什么连接会lostlost后重连为什么会报出异常?该问题不是紧急问题,先放放。

 

根据这几次的问题记录,试图找出其中的共性。想来想去,2.5版本和2.4版本(2.4版本平台持续运行较好)的最主要的区别有:

12.5版本多了一个公共库,插件共享这个库。

22.5版本多了一个类似ORM(对象关系映射)的库。

这几次出问题的特点都涉及这2个改变。后台线程都是rto跨库访问dap插件。而dap插件又使用ORM操作内存数据库。

 

先翻翻ORM的代码。看看能否找出线索。功夫不负有心人,找出一个巨大bug

以下函数存在线程安全问题。

int SplitString(const char *s0,vector<string>& t,char deli)

{

   char *s = strdup(s0);

   char seps[2];

   seps[0] = deli;

   seps[1] = '/0';

   char *token = strtok( s, seps );///<获取第一个token

   while( token != NULL )

   {

           t.push_back(token);

      token = strtok( NULL, seps );///<获取下一个token

     

   }

   free(s);

   return t.size();

}

strtok不是一个线程安全函数,他必须用一个全局的变量记录字符串(或者字符串下一个处理位置)。如果多线程下同时访问则会存在不可预期的结果。

解决方法:自己实现split,不用strtok

int SplitString(const char *s0,vector<string>& t,char deli)

{

         const unsigned int ITEM_SIZE = 32;

         const char *p = s0;

         unsigned int buf_size = ITEM_SIZE;

         char *buf = new char[buf_size];

         unsigned int len = 0;

         do {

                   char ch = *p;

                   if (ch==deli||ch=='/0') {

                            buf[len] = '/0';

                            t.push_back(buf);

                            if (ch=='/0')

                                     break;

                            len = 0;

                   }

                   else {

                            if (len==buf_size-1) {

                                     buf_size <<=1;

                                     char *tmp_buf = new char[buf_size];

                                     memcpy(tmp_buf,buf,len);

                                     delete []buf;

                                     buf = tmp_buf;

                            }

                            buf[len++] = ch;

                   }

                   p++;

         } while(1);

        

         delete []buf;

         return t.size();

}

 

晚上7:30替换程序,重启平台。期待中...