我最近在调试一个程序,主要解决实时采集存储。采用多线程的方法实现,但一直出现内存访问违例崩溃。
先把程序框架分析一下:程序:MFC WIN32, 开发环境:VS2005, 处理器AMD Athlon64(tm)X64 dual,操作系统32位WinXP,编译目标X86程序通过一个回调函数以一定的帧率采集图像,我开辟一个工作者线程,并设置了一个BUFFERSIZE(常量)大小的环形缓冲区,每个缓冲区单元是一个帧结构。然后调用如下函数开辟一个工作者线程和一个semaphore用于同步,
                  hSemaphore = CreateSemaphore(NULL, 0, 3, NULL);
pWorkThrd = AfxBeginThread(ThreadFunc,
(LPVOID) 1,
THREAD_PRIORITY_ABOVE_NORMAL,
CREATE_SUSPENDED);

ASSERT(pWorkThrd );
        // Not let the thread terminate by itself
pWorkThrd->m_bAutoDelete = FALSE;
pWorkThrd->ResumeThread();
在工作者线程函数ThreadFunc中等待信号灯激发,并实现对缓冲区内容的硬盘写入操作;而回调函数中负责内存的搬运工作;
但是每次只能正常运行BUFFERSIZE(即缓冲区大小)次数的正确内存拷贝,然后就发生内存访问违例异常。
被这个问题困扰了很久,希望了解的人能够帮忙回答一下。先说谢谢了。

解决方案 »

  1.   

    你缓冲区使用什么函数申请的?
    多线程的话。建议使用GlobalAlloc,GlobalFree如果是new出来的。还是开辟一个足够大的静态内存区域吧。我说的是全局的。
      

  2.   

    我new出来的,这个是不是会发生问题的?
      

  3.   

    楼主提供的代码看不出问题。看看当前堆栈,是哪里引发的访问异常。用GlobalAlloc可以对堆内存的分配进行同步处理,但注意他不会调用构造函数(如果你是在给对象分配内存的情况下)。
      

  4.   

    还是要贴以下我的内存分配代码,虽然烂得不好意思拿出来,但为了解决问题,没办法了
    这个是我的结构:
    typedef struct _FRAMENODE_
    {
    _FRAMENODE_ *pNext;
    FRAMEINFO frameInfo;
    CRITICAL_SECTION critical_sec;
    }FrameNode, *PFrameNode;其中FAMEINDO是另外一个struct,记录帧信息,重要的是有一个指向帧内容的指针lBufPtr。下面是我在主线程的消息响应函数里分配内存的代码:
    其中,m_pFrameBuffer是指向环形缓冲区开始的标记指针,m_pCurDispFrame是当前显示指针,同时用来操作环形缓冲区的初始化。lBufSizeG是在准备阶段获得的需要缓冲区单元大小(该数据经验证没有问题),CRITICAL_SECTION 我注释掉测试过,也一样发生问题。
    if(NULL == m_pFrameBuffer)
    {
    FrameNode *pTempNode = new FrameNode;
    if(!pTempNode)
    AfxMessageBox("Create FrameNode failed");
    pTempNode->pNext = NULL;
    pTempNode->frameInfo.lBufPtr = new BYTE[lBufSizeG];
    if(!pTempNode->frameInfo.lBufPtr)
    AfxMessageBox("Create Buffer failed!");
    m_pFrameBuffer = pTempNode;
    m_pCurDispFrame = m_pFrameBuffer;
    m_pCurSaveFrame = m_pFrameBuffer;
    //Initialize CriticalSection
    InitializeCriticalSection(&pTempNode->critical_sec);
    #ifdef _DEBUG
    OutputDebugString(" Allocate a buffer!");
    #endif
    }
    for(int i = 0; i< BUFFERSIZE-1; i++)
    {
    FrameNode *pTempNode = new FrameNode;
    pTempNode->pNext = NULL;
    pTempNode->frameInfo.lBufPtr = new BYTE[lBufSizeG];
    //InitializeCriticalSection(&pTempNode->critical_sec);
    m_pCurDispFrame->pNext = pTempNode;
    m_pCurDispFrame = pTempNode;
    #ifdef _DEBUG
    OutputDebugString(" Allocate a buffer!"); 
    #endif
    } m_pCurDispFrame->pNext = m_pFrameBuffer;
    m_pCurDispFrame = m_pFrameBuffer;还是需要大家多多帮助呀。今天一天在线等。
      

  5.   

    应该是权限问题,你使用VirtualProtectEx,在网上搜索他的用法吧,我很久没用过了,忘记他的参数什么的了,Google上搜,很多。我以前也遇到过类似的问题,在Google上搜索的
      

  6.   

    FrameNode *pTempNode = new FrameNode; 
    new 使用 malloc申请内存。
    你把指针给了下面的变量?
    m_pCurDispFrame->pNext = pTempNode; 
    m_pCurDispFrame = pTempNode; 怎么没有见过你delete?
    是否在不同的线程中delete?
    如果是的。又不想改程序那么把afxmem.cpp当中的
    new函数.malloc 和 _malloc_dbg
    delete函数 free 和 _free_dbg
    修改为GlobalAlloc和GlobalFree看看。
      

  7.   

    是的,因为是ring buffer,一般总会有三个指针分别来指ring buffer起始,当前写入和当前写出么,应该没错吧。

    我在同一个主线程delete的,就是结束的消息响应函数中做的。
      

  8.   


    在同一个进程中应该不存在权限的问题呀。我遇到的情况是对于申请的Heap第一次是可以访问的,但第二次再访问就发生崩溃了,就是访问非法。
      

  9.   

    因为有个DLL没有符号文件,所以栈回溯不是很完整。出错代码在这里(memcpy函数内部)
    Dword_align:
            test    edi,11b         ;U - destination dword aligned?
            jnz     short CopyLeadUp ;V - if we are not dword aligned already, align        shr     ecx,2           ;U - shift down to dword count
            and     edx,11b         ;V - trailing byte count        cmp     ecx,8           ;U - test if small enough for unwind copy
            jb      short CopyUnwindUp ;V - if so, then jump        rep     movsd           ;N - move all of our dwords
            jmp     dword ptr TrailUpVec[edx*4] ;N - process trailing bytes在红色那里崩溃了
    Output的exception是Access violation writing location 0xaddress源代码中的memcppy调用是:
    memcpy(m_pCurDispFrame->frameInfo.lBufPtr,
    DstFrameInfo.lBufPtr, (size_t)DstFrameInfo.lBufSize);然后我用GlobalAlloc函数了,也是一样的崩溃。
    所有的内存都只能正确访问一次,再访问出错。
      

  10.   

    DstFrameInfo.lBufSize看看这个值是否被溢出内容修改。很像内存越界
      

  11.   

    计算指向BUFF节点的计数是不是计错了
      

  12.   

    malloc从heap申请内存都有一个连信息存放你申请内存的信息。一旦被越界擦掉。那么会有无法预料的错误。最常见的就是delete不掉。
      

  13.   

    现在先分析一下dump文件哎,自己加油了。