首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ Builder >

写了一个接收模块,很简单,异常也很奇怪 指针有关问题

2012-03-02 
写了一个接收模块,很简单,错误也很奇怪 指针问题C/C++ code#include stdio.h#include InterWin.h#incl

写了一个接收模块,很简单,错误也很奇怪 指针问题

C/C++ code
#include <stdio.h>#include "InterWin.h"#include <IniFiles.hpp>//---------------------------------------#pragma package(smart_init)static  CRITICAL_SECTION    Memcopy;//公共缓冲区临界区static  TAG_INTERBUF        InterBuf;// 公共缓冲区static  bool                IsRun;static CMsgServer           *Serv;TInterWin::TInterWin(CMsgServer *msgServer){    Serv = msgServer;    IsListen = false;    IsRun    = false;}TInterWin::~TInterWin(){    //删除临界区    DeleteCriticalSection(&Memcopy);    if(sockSrv != NULL)        delete sockSrv;    //delete TagArgs->Args;    if(Arg != NULL)        delete Arg;}//socket初始化bool __fastcall TInterWin::Listen(){    //定义版本号    WORD wVersionRequested;    WSADATA wsaData;    int err;    if(IsListen)    return false;    IsListen = true;    wVersionRequested = MAKEWORD( 2, 2 );    TIniFile *ini;    ini = new TIniFile(ChangeFileExt(Application->ExeName, ".ini" ));    //读取工作模式    int Port =ini->ReadInteger("TCPIP", "Port", 0);     //缺省为服务器模式    delete ini;    err = WSAStartup( wVersionRequested,&wsaData);    if( err != 0)    {        return false;    }    //版本是否正确    if( LOBYTE( wsaData.wVersion)!= 2||        HIBYTE(wsaData.wVersion)!= 2)    {        WSACleanup();        return false;    }    sockSrv =  new SOCKET;    //创建socket             IPV4    TCP    *sockSrv = socket(AF_INET,SOCK_STREAM,0);    //服务端结构体    SOCKADDR_IN addrSrv;        memset(&addrSrv,0,sizeof(SOCKADDR_IN));    addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);//IP地址  htonl:将主机字符顺序转化成网络顺序    addrSrv.sin_family = AF_INET; //协议类型 IPV4    addrSrv.sin_port= htons(Port);//端口号 16位主机字符转化网络字符    ///梆定socket到端口    bind(*sockSrv,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));    err = listen(*sockSrv,128); //第二个参数表示最大连接数 当为AF_INET时最大是128    if(err!=0)    {        //getErrors        err = WSAGetLastError();    }    Arg = new TAG_THREADARG;    Arg->Args = (void *)sockSrv;    //Arg->handle = m_hWnd;    //初始化临界区    InitializeCriticalSection(&Memcopy);    //开始监听线程    _beginthreadex(NULL , 0 ,StartListenThread,(void *)Arg , 0 , 0);    //数据传递线程    //_beginthreadex(NULL , 0 ,SendDataThread,NULL , 0 , 0);        return true;    }//==============================================================================// 端口监听线程    阻塞模式//==============================================================================unsigned __stdcall  TInterWin::StartListenThread(void* pArguments ){    Sleep(5000);    TAG_THREADARG *TagArgs = (TAG_THREADARG *)(pArguments);    SOCKET *test = (SOCKET *)TagArgs->Args; //(TAG_THREADARG *)(pArguments)    while(true)    {        SOCKADDR_IN addrClient;        int len = sizeof(SOCKADDR);        SOCKET sockConn =  accept(*test,(SOCKADDR*)&addrClient,&len);                //设置接收超时时间 超时自动断开连接        //int timeout = 40*1000;        //int itemp = setsockopt(sockConn,SOL_SOCKET,SO_RCVTIMEO, (const char *)&timeout,sizeof(int));        //连接信息加入映射表·         //ClientList.insert(map<unsigned int, SOCKADDR_IN>::value_type(sockConn,addrClient));        TAG_THREADARG *info = new TAG_THREADARG;        SOCKET *sock = new SOCKET;        *sock = sockConn;        info->Args = (void *)sock;        //info->handle = TagArgs->handle;                _beginthreadex(NULL , 0 ,disposeMessageThread,(void *)info , 0 , 0);    }    return 0;}//==============================================================================// 消息接收线程//==============================================================================unsigned __stdcall TInterWin::disposeMessageThread(void* pArguments){    TAG_THREADARG *info = (TAG_THREADARG *)pArguments;    SOCKET *sock = (SOCKET *)info->Args;       BYTE *ListBuf = new BYTE[ECGDATABUF];  //每包81个字幕 每400ms一次。定 7*81个缓冲区 约2.8秒的数据    ZeroMemory(ListBuf,ECGDATABUF);    unsigned int *Position = new unsigned int;  //标志缓冲区的结束位置    *Position = 0;    //delete info->Args;    //info->Args = NULL;    char revBuf[ECGDATABUF]; //这是接收缓冲区       while(true)    {        memset(revBuf,0,ECGDATABUF);        int recleng = recv(*sock,revBuf,ECGDATABUF,0);           if(recleng <= 0 || IsRun == true)        {//连接断开            //将连接在连接列表中去除            shutdown(*sock ,2);//关闭套接字            delete   sock;            delete   info;            delete[] ListBuf;            delete   Position;            break;        }           //printf("%x",revBuf[0]);        //没有超过缓冲区才处理        if((*Position + recleng) < ECGDATABUF)        {            memcpy(ListBuf + *Position,revBuf,recleng); //复制到缓冲区            *Position += recleng;        }        else        {//为了接收最新的数据,将前面接收到的数据进行丢弃            //memmove(&ListBuf[0],&ListBuf[recleng], 567-recleng);            //memcpy(ListBuf + *Position,revBuf,recleng);            //ZeroMemory(&ListBuf[0],ECGDATABUF);            //*Position = 0;        }        //if(*Position >= 1050)//凑够5秒数据一起发        //{            DisposeData(ListBuf,Position);        //}    }     return 1;}//==============================================================================// 判断是否是完整数据包     //==============================================================================unsigned __stdcall TInterWin::DisposeData(BYTE *DataBuf, unsigned int *pos){    int  bufstart = 0;  //数据包在缓冲区的开始位置    int  bufend   = 0;  //数据包在缓冲区的结束位置    bool isok = false;    int dataleng = 0;    int i;    unsigned int Count = *pos;    //注意 循环中不能移动数据包 否则i指的位置错误 低级错误    for(i = 0; i < Count; i++)    {        if(DataBuf[i] == 0x55 && DataBuf[i+1] == 0xAA)        {            if(bufstart == 0 && bufend == 0 && isok == false)            {//这是第一次检测到同步字                bufstart = i; //记录同步字开始位置                isok = true;  //表示前面已经检测到同步字了            }            else if(isok == true)            {//这是第二次检测到同步字表示前面已经有完整的数据表了                bufend = i; //结束位置                dataleng = bufend - bufstart;                EnterCriticalSection(&Memcopy);                Serv->packetParser(&DataBuf[bufstart],dataleng);    //收到包直接发,不用公共缓冲区                LeaveCriticalSection(&Memcopy);                //memmove(&DataBuf[0],&DataBuf[dataleng], ECGDATABUF - dataleng);//移动缓冲区                //*pos -= dataleng; //改变结束位置                //这个第二包的开始,因为上面已经检测到同步字了。                bufstart = bufend;// - dataleng);                //bufend   = 0;                //isok     = false;            }        }    }    //循环结束判断是否有数据包(只有一个数据包的情况)    if(isok == true) //有同步字    {        if(DataBuf[bufstart] == 0x55 && DataBuf[bufstart+1] == 0xAA)        {            //if((DataBuf[*pos-1]&0xFF) == (*pos-2))    //先不进行校检和检测            {                EnterCriticalSection(&Memcopy);                Serv->packetParser(&DataBuf[bufstart],84);                LeaveCriticalSection(&Memcopy);                isok = false;                bufstart += 84;            }        }    }    memmove(&DataBuf[0],&DataBuf[bufstart], ECGDATABUF - bufstart);//移动缓冲区    *pos -= bufstart; //改变结束位置    if(*pos < 0)    *pos = 0;        return 0;}//数据发送线程unsigned __stdcall TInterWin::SendDataThread(void* pArguments){   /* while(true)    {        if(InterBuf.position < 83)        {            Sleep(30);            continue;        }        EnterCriticalSection(&Memcopy);        Serv->packetParser(InterBuf.Buff, InterBuf.position);        LeaveCriticalSection(&Memcopy);        Sleep(10);            }  */    return 0;} 



现在的问题是缓冲区结尾指针*Position 有时会变成一个巨大的数,关键是巨大的数的时候 if((*Position + recleng) < ECGDATABUF)这个判断居然还能进去,ECGDATABUF数据不到一万。我已经全部重新编译还是不行。GodeGader报错信息如下
Error 00001. 0x140200 (Thread 0x00C0):
Pointer arithmetic underrun: 0x03B55600-68, that is at offset 0-68 in block
 0x03B55600 (size 6720).
Call Tree:
  0x0065CFD9(=MB800N.exe:0x01:25BFD9) InterWin.cpp#165
  0x00888064(=MB800N.exe:0x01:487064)
  0x00888097(=MB800N.exe:0x01:487097)
  0x7C80B699(=kernel32.dll:0x01:00A699)

Error 00002. 0x100400 (Thread 0x00C0):
Access in invalid memory: Attempt to access 908 byte(s) at 0x03B555BC.
memcpy(0x03B555BC, 0x020AE460, 0x38C [908]) 

Call Tree:
  0x0065CFDF(=MB800N.exe:0x01:25BFDF) InterWin.cpp#165
  0x00888064(=MB800N.exe:0x01:487064)
  0x00888097(=MB800N.exe:0x01:487097)
  0x7C80B699(=kernel32.dll:0x01:00A699)

InterWin.cpp#165行就是上面的memcpy(ListBuf + *Position,revBuf,recleng); //复制到缓冲区
这句话。实在找不出问题了。高手指教呀。



[解决办法]
楼主分享一下 你找到什么问题了 如何解决的
小弟也在尝试线程 用的不好 还在摸索中 
借你的程式学习一下。
[解决办法]
recv(*sock,revBuf,ECGDATABUF,0)
应该是这句的事儿吧。。。
总之提示说的是你访问了负空间。
[解决办法]
等老妖给你移到茶馆,你把分数散了吧

热点排行