打印

delete[]结果引发异常

[复制链接]
13577|35
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
冰清玉洁|  楼主 | 2011-6-29 15:37 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
一个由VC6迁移到VC2008SP1的工程。
使用了Cypress的USB库:CyUSB.lib(静态链接,无dll文件)

症状:
在主线程中我new了一个字符串,然后作为参数,传递给线程,线程中使用该字符串,然后delete[],结果引发异常。
沙发
冰清玉洁|  楼主 | 2011-6-29 15:54 | 只看该作者
工程设置:Debug multithread DLL(/MDd)

自我诊断:
改用GlobalAlloc/GlobalFree依然无济于事。我认为CyUSB.lib可能静态链接到了CRT库,而我的版本是使用动态链接。不过,我改变了工程设置为“静态使用MFC、使用CRT库的多线程非DLL版本”,依然会报错。
在VC6中一切正常。

使用特权

评论回复
板凳
wenfen| | 2011-6-29 16:02 | 只看该作者
不妨提供一下代码

使用特权

评论回复
地板
冰清玉洁|  楼主 | 2011-6-29 16:12 | 只看该作者
代码:
C/C++ code
//CEmuDevice继承自CCyUSBDevice,该类由CyUSB.lib导出
LRESULT CEmuDevice::SendCommand(COMMAND nCommand, WPARAM wParam/* =0 */, LPARAM lParam/* =0 */)
{
    ASSERT(IsOpen());

    WaitWorkerThreadExit();

    PWORKITEM pWorkItem = new WORKITEM;
    pWorkItem->wParam = wParam;
    pWorkItem->lParam = lParam;
    pWorkItem->pDevice = this;
    switch(nCommand)
    {
        case CONFIG_EMULATOR:
        {
            LPCTSTR lpszConfigFile = (LPCTSTR)wParam;
             LPTSTR lpszPathName = new TCHAR[_tcslen(lpszConfigFile)+1];
             ZeroMemory(lpszPathName, (_tcslen(lpszConfigFile)+1)*sizeof(TCHAR));
             _tcscpy_s(lpszPathName, (_tcslen(lpszConfigFile)+1)*sizeof(TCHAR), lpszConfigFile);

            pWorkItem->wParam = (WPARAM)lpszPathName;
            pWorkItem->uCmd = CONFIG_EMULATOR;

            break;
        }

        ……
    }
   
    if(pWorkItem != NULL)
    {
        if(m_hWorkerThread == NULL)
        {
            m_hWorkerThread = ::CreateThread(NULL, 0, CommandDispatchWorker, (LPVOID)pWorkItem, 0, &m_dwThreadID);//参数传入
            if(m_hWorkerThread == NULL)
            {
                TRACE0("Create command dispatch worker thread failed.\n");
                return 0;
            }
        }
    }

//线程函数
DWORD WINAPI CEmuDevice::CommandDispatchWorker(LPVOID lpParameter)
{
    ASSERT(lpParameter != NULL);

    WORKITEM* pWorkItem = (WORKITEM*)lpParameter;
    CEmuDevice* pDevice = pWorkItem->pDevice;
    WPARAM wParam = pWorkItem->wParam;
    LPARAM lParam = pWorkItem->lParam;

    ASSERT(pDevice != NULL);
    ASSERT(pDevice->m_hNeedStop != NULL);

    if(!pDevice->IsOpen())
    {
        return 1;
    }

    switch(pWorkItem->uCmd)
    {
        /* Board level commands */        
        case CONFIG_EMULATOR:
        {
            LPTSTR lpszConfigFile = (LPTSTR)wParam;
            pDevice->ConfigEmulator(lpszConfigFile);
            delete[] lpszConfigFile; //<------------异常

            break;
        }
        
        ……

    }
    delete[] pWorkItem;
    return 0;
}

使用特权

评论回复
5
lium| | 2011-6-29 16:28 | 只看该作者
是否存在SendCommand中没有运行case CONFIG_EMULATOR:里面的语句就到后面创建函数的代码啦的情况

使用特权

评论回复
6
guoyt| | 2011-6-29 16:35 | 只看该作者
估计与Unicode字符集有关,你把项目改成多字节字符集验证一下。

使用特权

评论回复
7
guoyt| | 2011-6-29 16:43 | 只看该作者
另外再调试一下,开一个内存窗口,监视从lpszPathName-0x20开始的内存,看看执行过程中是否发生变化。

使用特权

评论回复
8
hanwe| | 2011-6-29 16:57 | 只看该作者
你要delete的指针是在SendCommand中由CCyUSBDevice作为参数传给你的,我说的没错吧。
那么你知道这个指针在CCyUSBDevice中是如何创建的?

使用特权

评论回复
9
hanwe| | 2011-6-29 17:15 | 只看该作者
至少你怎么知道要用delete []而不是delete?甚至可能你根本不用自己释放,CCyUSBDevice会自己释放。

使用特权

评论回复
10
wenfen| | 2011-6-29 17:34 | 只看该作者
一个很重要很容易出你这种问题的做法是在dll中分配内存在exe中释放。这是非常不推荐的

使用特权

评论回复
11
冰清玉洁|  楼主 | 2011-6-29 17:56 | 只看该作者
那应该?

使用特权

评论回复
12
wenfen| | 2011-6-29 18:36 | 只看该作者
比如
void* CCyUSBDevice::Alloc()
{
return new char[20];
}
void CCyUSBDevice::Release(void *p)
{
delete [] p;
}

使用特权

评论回复
13
wenfen| | 2011-6-29 18:46 | 只看该作者
如果你到网上搜索容易搜索到这样做的原因,我就不罗嗦了

使用特权

评论回复
14
冰清玉洁|  楼主 | 2011-6-29 18:54 | 只看该作者
感谢楼上的回复。字符串是在EXE的主线程里分配的,在EXE的辅助线程里释放的。没有用到任何自己的DLL和第三方的DLL

使用特权

评论回复
15
wenfen| | 2011-6-29 19:04 | 只看该作者
哦,Cypress提供的是一个静态链接的lib,无DLL文件

使用特权

评论回复
16
冰清玉洁|  楼主 | 2011-6-29 19:15 | 只看该作者
改成multi byte就没问题了。

使用特权

评论回复
17
冰清玉洁|  楼主 | 2011-6-29 19:28 | 只看该作者
刚刚分配完内存之后,_CrtMemBlockHeader::pBlockHeaderPrev == NULL,继续执行到准备释放时,这个值被改变了

使用特权

评论回复
18
tian111| | 2011-6-29 19:35 | 只看该作者
其余的值都没有变吧?

使用特权

评论回复
19
冰清玉洁|  楼主 | 2011-6-29 19:47 | 只看该作者
没变~~~

使用特权

评论回复
20
wenfen| | 2011-6-29 20:05 | 只看该作者
改用Multi-Byte测一下

使用特权

评论回复
评分
参与人数 1威望 +1 收起 理由
eehomer + 1
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

307

主题

3250

帖子

5

粉丝