wei_ziyong
驱动牛犊
驱动牛犊
  • 注册日期2003-12-31
  • 最后登录2010-04-30
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望16点
  • 贡献值0点
  • 好评度16点
  • 原创分0分
  • 专家分0分
阅读:2672回复:10

线程造成内存泄露?

楼主#
更多 发布于:2004-06-07 20:35
    我在WIN32 DLL中用CreateThread()函数创建了一个线程,在线程中要使用一个64kbytes的堆空间,通过传给线程。函数线程能够正确的运行,但是当退出调用线程的程序后,出现了内存泄露的情况。
    在线程中,我已经用delete函数释放了分配的64kbytes的空间,可是,他说还剩下45Bytes的空间释放,出现内存泄露,请问这个应如和解决好啊?谢谢各位拉!
wei_ziyong
驱动牛犊
驱动牛犊
  • 注册日期2003-12-31
  • 最后登录2010-04-30
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望16点
  • 贡献值0点
  • 好评度16点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2004-06-08 12:55
    在要调用线程的主函数中分配64kBytes内存,然后,在把内存的地址传给在dll中的线程,当终止dll中线程的运行时,由dll中被调用的线程释放内存。
    我使用了CC++运行期库函数_beginthreadex还时遇到了上述的问题阿。我发现在主线程中用malloch和new来分配内存还是存在内存泄漏的情况,但是,在主线程中用 GlobalAlloc()和HeapAlloc()时能够暂时防止内存泄漏。这是怎么的一回事啊?
    使用了CC++运行期库函数_beginthreadex来创建线程,在线程中使用malloc和new函数分配内存,应该不会在产生内存泄漏才对阿!这又是怎么的一回事?
    再次,问一下使用_beginthreadex创建的线程,当调用他的主程序退出时,如果不显示的调用一些函数来终止线程的话,CC++运行期库能够自动调用_endthreadex()函数来终止线程的运行,是这样的么?
wei_ziyong
驱动牛犊
驱动牛犊
  • 注册日期2003-12-31
  • 最后登录2010-04-30
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望16点
  • 贡献值0点
  • 好评度16点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2004-06-08 17:03
   你的意思是不是,只要是传给DLL引出函数的指针,就只能够在只能在调用该函数的主程序中释放的指针?
   那么我这里还有个问题,我要写的那个线程要不停的调用driver中的函数,从硬件设备读数据。那个线程能够不停的从设备读数据,要把数据不停的存放到应用程序传给线程的那个缓冲区。
  如果缓冲区的由调用读数据的线程来维护、释放,当调用了创建线的函数过后,调用函数就退出了的嘛,缓冲区也就被释放了。读数据的线程就回读数据失败!这个问题你们没有什么好的注意啊?
下面有我的原代码。
wei_ziyong
驱动牛犊
驱动牛犊
  • 注册日期2003-12-31
  • 最后登录2010-04-30
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望16点
  • 贡献值0点
  • 好评度16点
  • 原创分0分
  • 专家分0分
地板#
发布于:2004-06-08 17:03
我的主要代码如下,你们帮我看看有什么不足,和错误,需要改正的!
谢谢!
在动态连接库中,
线程函数的定义如下:
typedef struct DataInfo{
ULONG  dwDSPAddr;
PULONG ReturnAddr;
ULONG  ReturnBufSize;
PULONG pReturnLength;
HANDLE *pEvent;

}*PDataInfo;
unsigned __stdcall ServiceThread(PVOID Param)
{
PDataInfo pRead = (PDataInfo)Param;
//Open device
........................
//传递事件
.............................
while(TRUE)
{
//WaitForSingleObject(hEvent,INFINITE);
DWORD flag=0;
while((flag=WaitForSingleObject(hEvent,0))!= WAIT_OBJECT_0)
{
if(!(*pRead->pKeepRunning))
{
//应用程序开辟的缓冲区,传给线程的地址线程退出时释放
delete pRead->ReturnAddr;
delete pRead;
CloseHandle(hDevice);
CloseHandle(hEvent);
return 0;
}
}
ULONG ReturnWrite = 0;
BOOL bResult = FALSE;
if(WriteFile(hDevice,
&pRead->dwDSPAddr,
4,
&ReturnWrite,
NULL
))
bResult = ReadFile(hDevice,
pRead->ReturnAddr,
pRead->ReturnBufSize,
pRead->pReturnLength,
NULL
);
else
bResult = FALSE;

if(bResult == FALSE)
{
delete pRead->ReturnAddr;
delete pRead;
pRead = NULL;
MessageBox(NULL,"取数据失败!","失败!",MB_OK);
return 0;
}else
{
if(SetEvent(*(pRead ->pEvent)))
MessageBox(NULL,"SetEvent","",MB_OK);
}
}
//应用程序开辟的缓冲区,传给线程的地址线程退出时释放
free(pRead->ReturnAddr);
delete pRead;
pRead = NULL;
return 0;

}
C6416DLL_API HANDLE CALLBACK GetDSPData(ULONG dwAddr,
PULONG  Buf,
ULONG   BufSize,
PULONG  pLengthByRead,
HANDLE  *pEvent
               )
{
unsigned  ThreadId;
HANDLE    hThread = NULL;
//准备取数据缓冲区
PDataInfo pInfo      = new(DataInfo);
pInfo->dwDSPAddr     = dwAddr;
pInfo->ReturnBufSize = BufSize;
if((pInfo->ReturnBufSize) > 0x10000)
pInfo->ReturnBufSize = 0xffff;
pInfo->ReturnAddr = Buf;
if(pInfo->ReturnAddr == NULL)
{
MessageBox(NULL,"缓冲区不存在!","失败!",MB_OK);
return false;
}
pInfo ->pReturnLength = pLengthByRead;
pInfo ->pEvent = pEvent;
hThread = (HANDLE)_beginthreadex(0,
       0x1000,
ServiceThread,
(PDataInfo)pInfo,
0,
&ThreadId);
if(hThread == NULL)
{

delete pInfo->ReturnAddr;
delete pInfo;
pInfo = NULL;
MessageBox(NULL,"创建线程失败!","失败!",MB_OK);
}
return hThread;
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
在应用程序中调用dll中创建的线程:

void CTestC6416Dlg::OnDma()
{
ULONG dwAddrDSP    = 0x10000;
ULONG nSize        = 0xffff;
ULONG LengthByRead = 1;
// PULONG ResultAddr  = (PULONG)malloc(nSize);
// PULONG ResultAddr  = (PULONG)new ULONG(nSize);
// PULONG ResultAddr  = (PULONG)GlobalAlloc(0,nSize);
PULONG ResultAddr  = (PULONG)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,nSize);
if(ResultAddr == NULL)
{
AfxMessageBox("内存分配失败!");
return;
}
//创建事件对象用于读数据同步
HANDLE hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
if(hEvent == NULL)
{
AfxMessageBox("创建事件对象失败!");
return;
}
//调用dll中的GetDSPData()函数创建线程,线程不停的从设备取数每次64kBytes
hThread = GetDSPData(dwAddrDSP,ResultAddr,nSize,&LengthByRead,&hEvent);
if(hThread == NULL)
{
AfxMessageBox("调用失败!");
return;
}
while(WaitForSingleObject(hEvent,INFINITE) == WAIT_OBJECT_0)
{
//显示头4个字节的数据
m_strData.Format("%x",*(ResultAddr));
CDialog::UpdateData(false);
ResetEvent(hEvent);
}
}
    我的线程如上定义的,不能够在ServiceThread线程中释放由CTestC6416Dlg::OnDma()分配的内存么?
    那我还就是怎样才能够让我的线程能够终止运行?
    能不能够在线程中设置一个bool值的变量,线程去检测这个变量的值,如果是指示要退出线程,
那么用上面的方式--采用return语句能够终止线程的运行么?他拥有的资源也能够释放么?
  
wei_ziyong
驱动牛犊
驱动牛犊
  • 注册日期2003-12-31
  • 最后登录2010-04-30
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望16点
  • 贡献值0点
  • 好评度16点
  • 原创分0分
  • 专家分0分
地下室#
发布于:2004-06-09 12:26
谢谢各位!我再看看书和资料
游客

返回顶部