2009年4月28日星期二

项目管理及C++基本编码守则-jhonglei


每天总结自己编写代码中所犯的错误,并反思出错的原因;总结所获取的经验;归纳编程的基本原则。

文档的编写:

以后所有提交的文档的文件名中写三部分:文件名-姓名-日期。文件名要简洁,语义清晰。这样文档多了容易查找

程序开发

 变量:命名规范
 函数的编写 
   注释:
 错误处理 函数参数检查
 内存管理
 版本控制
 日志系统
 
阅读以下书籍:
       《C++ Primer》
   《Effective C++》
以下几点是在程序开发过程中实际发现的应当遵守的地方。


  • 错误处理:


  • 有限状态自动机是保证 编程正确性,安全性的 有力武器。比如在网络编程时,状态记录有助于排错。


使满足状态的包才会被处理,不满足状态变迁的包将被丢弃。如只有登陆后才进行继续的处理。防止恶意包和欺骗行为。

任何不满足格式要求的包将被抛弃。
  •   一定要对收到的数据包的每一个字段进行长度检查,不满足长度要求得数据包进行抛弃。
  • 对数据包的源地址进行检查,不满足长度要求进行抛弃。
      例如:
         eyeBeam,语音和视频从不同的IP发送是不可以接受的。nettalk中途更换语音的发送IP也是不可以接受的。其语音包的负载大小:也必须是20个字节:20ms的数据。
对于大于20的语音包,直接抛弃。如我们的nettalk.当视频RTP包发送到语音RTP包的接收端口时,由于没有做长度检查,导致内存越界,使得接收SOcket被改写。。


指针越界问题:使用必要的边界检查。预防缓冲区溢出漏洞



如果可能,进行必要的协议分析,以保证程序的正确性。



  • 2,函数必须有两种返回值,1),程序是否正确执行,2),程序执行的结果

    错误检查是保证程序健壮性的必要因素。

  • 3,能用if条件判断的,不使用异常。

4,对于两种不同的协议,使用不同的端口进行处理。RTPRelay的命令包和RTP数据流应当分开。

5, 遵守最基本的命名规范,成员变量全部为private, 以m_*开头。。变量名应当容易理解,见名知意。

不要使用什么 dd ,zhu等看不出含义的名字。

变量的作用域越大,变量的命名应当越谨慎。

如有可能,不要使用全局变量。

禁止使用如下方式:

      #define PORT 18800

原因:很有可能出现宏重定义,且名字也不清晰。



6,动态内存的管理:尽量少用。

 使用内存检查工具检查内存内存泄露,如valgrind,但不要完全把希望寄托到检查工具上。

 编写内存安全的代码是程序开发人员的责任。Win32的RuntimeChecker



使用相匹配的new/delete

    char *pbuf = new char[len+1];

    delete [] pbuf;

使用valgrind:

[hongleij@hustp2psrv bin]$ valgrind -v --leak-check=full ./meridianClient



==11443== 1 errors in context 7 of 9:

==11443== Conditional jump or move depends on uninitialised value(s)

==11443==    at 0x418AE16F: pthread_mutex_init (in /lib/libpthread-2.5.so)

==11443==    by 0x418128DC: pthread_mutex_init (in /lib/libc-2.5.so)

==11443==    by 0x4010877: CMeridianThread::CMeridianThread() (CriticalSection.h:55)

==11443==    by 0x4015A80: StartRTPRelay (RTPMain.cpp:17)

==11443==    by 0x804868B: main (Client.cpp:7)



使用必要的初始化函数:

    CriticalSection()

 {   

    pthread_mutexattr_t mutex_attribute;

       

    pthread_mutexattr_init(&mutex_attribute);//add jianghonglei 081010

       

    pthread_mutexattr_settype(&mutex_attribute, PTHREAD_MUTEX_RECURSIVE);

       

    pthread_mutex_init(&mutex_, &mutex_attribute);

       

    pthread_mutexattr_destroy(&mutex_attribute);//add jianghonglei 081010

 }



7,使用CVS或SVN服务器来进行版本控制,并对文件目录的设置进行规范。
   维护以下部分:
     源代码,文档,参考资料
              尤其是跨平台程序的开发。win工程文件使用单独的目录,代码与配置清晰
              设置的目的不仅仅维护代码,而且包括文档,
              每个用户有不同的权限,每次提交必须添加注释,表明这次修改的目的,和测试结果

8, 编写可复用的代码。相当于对代码进行了多次测试。品质更容易保障。

9,统一的日志输出格式:正确区分编程错误,网络IO错误,和异常情况。可以支持模块化调试。

     如只输出某个或某几个模块的调试信息。

1),   调试信息以模块名开头如:KAD

2),  并区分错误信息的等级,类型:

3),  输出时间

10:绝不允许出现类似如下的情况:

   char * pBuf =NULL;

   std::cout<<pBuf;

11: 不允许出现函数需要返回值却没有返回值 的情况,例如

         int func()

{

     if(true)

  {

         return 1;

    }

//this place should add return !!!

}

最好保证函数有单一的入口和出口。

12: 调用网络相关函数,必须对错误情况/返回值进行检查。不允许不做检查的情况出现。!!!

    sendto,  recvfrom

    ReceiverAddr.sin_family = AF_INET;//IMOPTANT!!!!

                ReceiverAddr.sin_port=htons(18888);

                ReceiverAddr.sin_addr.s_addr=inet_addr(iter->ip);

13:为防止端口冲突,程序中所有端口在同一文件中配置。

14:  每行代码不超过80个字。目的:在比较时容易忽略掉。

15: C++异常的处理,如果使用,应当尽可能在最内层处理。

16:数据一致性是程序正确性最根本的保证。应当充分尊重数据库的黄金法则:“同一个意思只表达一次”。至少包括两层意思:代码简练,少冗余。

17.不得做如下调用,在同一函数中调用2次inet_ntoa函数;

    RTPAdd(localIP,AVIO_PORT,

        inet_ntoa(pMgr->m_CalleeAddr.sin_addr),ntohs(pMgr->m_CalleeAddr.sin_port),

        inet_ntoa(pMgr->m_SuperNode.sin_addr),MERIDIAN_COMMAND_PORT

        ,NULL,NULL,GetTickCount());



18: 调用sendto()时,必须是系统支持的库函数
 void CAVIOMgr::OnRelayCommand(const char * ppc,int recvPackLen,SOCKADDR *recvAddr)
{
            SOCKADDR_IN pingAddr ;//TODO 为什么必须要进行一次转换??          
            memcpy(&pingAddr,recvAddr,sizeof(SOCKADDR_IN) );
            int bytesSended = m_Socket.SendTo((const char *)tmpBuf.GetBufferPrt(),tmpBuf.GetWritePos(),(SOCKADDR*)&pingAddr);
            //否则会产生10047 WSAEAFNOSUPPORT 错误   

}
19,select的使用:
                if( FD_ISSET( pMgr->m_Socket.GetSocket(), &writefds )  )
                {
                    pMgr->processPackSend();
                }
                if( FD_ISSET( pMgr->m_Socket.GetSocket(), &readfds ) ) //不是 else if
                {
                }
20:创建项目的Bug错误列表。
        表明程序的修订状况。
21: 出现Stack错误。
      在调试状态没有问题,不调试出现问题。
     原因:某些变量在使用时没有初始化。。
22: 保证程序的健壮
   程序的
 


================================


l99.com ->  相机照片,时间,GPS数据整合 -〉应用



未来的信息搜索 --〉 依时间轴依次排列,关联度(where ,what,time),





拼车网 --〉撮合率  凡事预则立 (临时需求)

火车票

游戏组队

             信息的过滤和筛选--〉有用信息,BBS,





51758855--719





但>2M*7K=

实际用户数:license

    >30-40 CPS

    2get 1put  30*2 =60读

用户数据量:IMS标准 3GPP 30K

CSF

话单

DNS 解析:

nokia sip stack

ims mar maa


没有评论: