帮忙看一段C++代码 ,多线程 指针 问题

spotatoes 2008-11-20 07:18:48
/********
大家好,帮我看看这段代码;
主要是为了实现分线程来处理数据,就是FlashGet或Thunder 下载一样的原理;

有N多少数据要处理;

要用线程来加快进度,每个线程负责一段数据处理;

这个线程个数可以指定,用户可以设置或程序固定用几个线程来处理;比如为 10

一开始创建 10线程 ,然后这10个线程中任何一个结束时都自动再创建一个副本线程运行,

确保有10个线程在工作 (当然要判断是否有待处理的数据 是吧 )


//下面是我自己想到的方式处理,但是有问题,运行一会就内存泄露了;请各个大虾们帮帮忙看看
******/


//
#include "stdafx.h"
#define _CRT_RAND_S
//
#include <windows.h>
#include <iostream>
using namespace std;

//
long lWantP = 100000; //待处理数据条数
int nMaxThread = 5; //分多少个线程来处理
HANDLE* hThread = NULL; //子线程句柄
HANDLE hMain = NULL; //主线程句柄

//
int GetPVal(void);
struct sctTh{
HANDLE bDelete; //保存子线程 自已创建线程时要CloseHandle的句柄
HANDLE hThread; //子线程本身执行的句柄
int lVal; //要处理的数据值,这里只做最简单的 整型处理
};

sctTh* pTh = NULL;
//
CRITICAL_SECTION g_cs = {0};
CRITICAL_SECTION o_cs = {0};

DWORD WINAPI ClidThread(LPVOID l)
{
sctTh* th = reinterpret_cast< sctTh* >( l );

if( !th ){ return 1; }
if( th->bDelete )
{
CloseHandle( th->bDelete );
th->bDelete = NULL;
}
::EnterCriticalSection( &o_cs );
cout<<" CT val: " << th->lVal <<endl;
::LeaveCriticalSection( &o_cs );
th->lVal++; //这里为了测试,只是简单+1后抛弃这个数据

int val = GetPVal();
if( val )
{
th->bDelete = th->hThread ;
th->lVal = val;
th->hThread = ::CreateThread(NULL,0,LPTHREAD_START_ROUTINE(&ClidThread),LPVOID( th ),0,NULL);
}
return 0;
}
//
DWORD WINAPI MainThread(LPVOID l)
{
hThread = new HANDLE[nMaxThread];
pTh = new sctTh [nMaxThread];
//

memset( pTh,0, sizeof(sctTh)*nMaxThread );
memset( hThread,0,sizeof(HANDLE)*nMaxThread);

//创建几个子线程来运行,直到处理完所有数据为止,线程结束后自动判断是否再次创建线程来保存有 nMaxThread 个线程在运行
for(int i=0; i<nMaxThread; i++)
{
int val = GetPVal();

if( !val ){ continue; }

pTh[i].bDelete = NULL;
pTh[i].hThread = &hThread[i];
pTh[i].lVal = val;
hThread[i] = ::CreateThread(NULL,0,LPTHREAD_START_ROUTINE(&ClidThread),LPVOID( &pTh[i] ),0,NULL);
}
//等所有线程结束
::WaitForMultipleObjects( nMaxThread,hThread,TRUE,INFINITE );
for( int i=0; i<nMaxThread; i++ )
{
CloseHandle( hThread[i] ); hThread[i] = NULL;
}

delete [] pTh;
delete [] hThread;hThread = NULL;
return 0;
}
//
int GetPVal(void)
{
int rel = 0;
::EnterCriticalSection( &g_cs );
if( lWantP > 0)
{
rel = lWantP-- ;
}
::LeaveCriticalSection( &g_cs );
return rel;
}
//
int _tmain(int argc, _TCHAR* argv[])
{
::InitializeCriticalSection( &g_cs );
::InitializeCriticalSection( &o_cs );
hMain = ::CreateThread(NULL,0,LPTHREAD_START_ROUTINE(&MainThread),LPVOID(0),0,NULL);
//if( !hMain ){ cout<<"Thread Create Failed !!"<<endl; }
::WaitForSingleObject(hMain,INFINITE);
Sleep(1000);
::DeleteCriticalSection( &g_cs );
::DeleteCriticalSection( &o_cs );
return 0;

}
...全文
169 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
spotatoes 2008-11-21
  • 打赏
  • 举报
回复
多谢提醒哈,终于给搞定了;;那个东西不起作用了哈,可能是因为hThread在运行更改了里面的值造成的,

WaitForMultipleObjects这个好像等到运行了一半就不返回了,










#include "stdafx.h"
#define _CRT_RAND_S
//
#include <windows.h>
#include <iostream>
using namespace std;

//
long lWantP = 34300; //待处理数据条数
int nMaxThread = 10; //分多少个线程来处理
HANDLE* hThread = NULL; //子线程句柄
HANDLE hMain = NULL; //主线程句柄
HANDLE* hEvent = NULL; //所有事件句柄

//
int GetPVal(void); //返回待处理的数据,返回0 表示没有了

struct sctTh{
HANDLE bDelete; //保存子线程 自已创建线程时要CloseHandle的句柄
HANDLE* hThread; //子线程本身执行的句柄
int lVal; //要处理的数据值,这里只做最简单的 整型处理
int eId; //对应的事件ID值 与 hEvent 指针对应
};

sctTh* pTh = NULL;
//
CRITICAL_SECTION g_cs = {0};
CRITICAL_SECTION o_cs = {0};

void CreateChildThread(sctTh* st);

//
DWORD WINAPI ClidThread(LPVOID l)
{
sctTh* th = reinterpret_cast< sctTh* >( l );

if( !th ){ return 1; }
::WaitForSingleObject( hEvent[th->eId], INFINITE );
//if( !SetEvent( hEvent[th->eId] ) )
{
// cout<<" here has a error hEvent["<<th->eId<<"] Coundn't SetEvent signed"<<endl;return 2;
}
if( th->bDelete )
{
CloseHandle( th->bDelete );
th->bDelete = NULL;
}
th->lVal++; //这里为了测试,只是简单+1后抛弃这个数据

int val = GetPVal();

SetEvent( hEvent[th->eId] );

if( val )
{
::EnterCriticalSection( &o_cs );
cout<<" GET val: " << val <<endl;
::LeaveCriticalSection( &o_cs );

th->bDelete = *th->hThread ;
th->lVal = val;
(HANDLE)*th->hThread = ::CreateThread(NULL,0,LPTHREAD_START_ROUTINE(ClidThread),LPVOID( th ),0,NULL);
//CreateChildThread(th);
}
return 0;
}
//
void CreateChildThread(sctTh* st)
{
HANDLE close = (*st->hThread) ;
(*st->hThread) = CreateThread(NULL,0,LPTHREAD_START_ROUTINE(&ClidThread),LPVOID( st ),0,NULL);

if( ! *st->hThread ){
cout<<"Create Error!"<<endl;
}
CloseHandle( close );
}
DWORD WINAPI MainThread(LPVOID l)
{
hThread = new HANDLE[nMaxThread];
pTh = new sctTh [nMaxThread];
hEvent = new HANDLE[nMaxThread];

memset( pTh,0, sizeof(sctTh)*nMaxThread );
memset( hThread,0,sizeof(HANDLE)*nMaxThread);

//创建几个子线程来运行,直到处理完所有数据为止,线程结束后自动判断是否再次创建线程来保存有 nMaxThread 个线程在运行
for(int i=0; i<nMaxThread; i++)
{
hEvent[i] = CreateEvent(
NULL, //Default EventAttributes
FALSE, //
TRUE, //no signed at init
NULL // no name
);
if( !hEvent[i] )
{
cout<<" Couldn't Create Event now!!!"<<endl;break;
}
int val = GetPVal();
::EnterCriticalSection( &o_cs );
cout<<"Get Val:"<<val<<endl;
::LeaveCriticalSection( &o_cs );
if( !val ){ break; }

pTh[i].eId = i;

pTh[i].bDelete = NULL;
pTh[i].hThread = &hThread[i];

pTh[i].lVal = val;
hThread[i] = ::CreateThread(NULL,0,LPTHREAD_START_ROUTINE(&ClidThread),LPVOID( &pTh[i] ),0,NULL);
//Sleep(100);
if( ! hThread[i] )
{
cout<<"Create T F"<<endl;
}

}
//等所有线程结束
///::WaitForMultipleObjects( nMaxThread,hThread,TRUE,INFINITE ); //THERE have a problem


//就这样笨办法等它完哟,很可能有隐患哟
while( lWantP )
{
Sleep(1000);
}
cout<<"ALL FINISHED <<endl;

for( int i=0; i<nMaxThread; i++ )
{
CloseHandle( hThread[i] ); hThread[i] = NULL;
}
cout<<"CLOSE ALL CHILD"<<endl;

delete [] pTh; pTh = NULL;
delete [] hThread;hThread = NULL;


delete [] hEvent; hEvent = NULL;
return 0;
}

int _tmain(int,char**)
{
::InitializeCriticalSection( &g_cs );
::InitializeCriticalSection( &o_cs );

HANDLE m =(
::CreateThread( NULL, 0, LPTHREAD_START_ROUTINE(&MainThread), NULL, 0, NULL )
);
if( m )
{
::WaitForSingleObject( m ,INFINITE );
}else{
cout<<" Main Thread wasn't Created" <<endl;
}

::LeaveCriticalSection( &g_cs );
::LeaveCriticalSection( &o_cs );
return 0;
}
//
int GetPVal(void)
{

int rel = 0;
::EnterCriticalSection( &g_cs );
if( lWantP > 0)
{
rel = lWantP-- ;
}
::LeaveCriticalSection( &g_cs );
return rel;
}


rularys 2008-11-21
  • 打赏
  • 举报
回复
那是因为下面这句返回了:
//等所有线程结束
::WaitForMultipleObjects( nMaxThread,hThread,TRUE,INFINITE );

接着会执行:
delete [] pTh;
delete [] hThread;
hThread = NULL;

但是这时候你的线程并没有全部结束,pTh还在被使用

rularys 2008-11-21
  • 打赏
  • 举报
回复
楼主为什么不用线程池?
wuxiaoqiang118 2008-11-21
  • 打赏
  • 举报
回复
for(int i=0; i <nMaxThread; i++)
{
int val = GetPVal();

if( !val ){ continue; }//我写错,应该是break;

pTh[i].bDelete = NULL;
//为什么是取地址值呢??
pTh[i].hThread = &hThread[i];
pTh[i].lVal = val;
hThread[i] = ::CreateThread(NULL,0,LPTHREAD_START_ROUTINE(&ClidThread),LPVOID( &pTh[i] ),0,NULL);
}
spotatoes 2008-11-20
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 ztz0223 的回复:]
还有:
你把这个改成:
C/C++ codelonglWantP=10;//待处理数据条数
不用10000
你就可以看到
有很多线程没有执行,却被分配了句柄
明显不能被显式回收
因此,这里有两个建议:
1、建立的子线程可以自分离
2、new和delete是不是因为线程的不执行而不配对,那自然也会内存泄露
[/Quote]

.
选 让待执行的条数 大于这个最大线程数 nMaxThread,也就是一开始至少10个线程;;

for(int i=0; i<nMaxThread; i++)
{
int val = GetPVal();

if( !val ){ continue; }//我写错,应该是break;

pTh[i].bDelete = NULL;
pTh[i].hThread = &hThread[i];
pTh[i].lVal = val;
hThread[i] = ::CreateThread(NULL,0,LPTHREAD_START_ROUTINE(&ClidThread),LPVOID( &pTh[i] ),0,NULL);
}



我试了就一个子线程来分别执行,执行第一,二次没问题,当执行到第三次时指针就为无效值了.hThread
spotatoes 2008-11-20
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 cyxisgreat 的回复:]
//创建几个子线程来运行,直到处理完所有数据为止,线程结束后自动判断是否再次创建线程来保存有 nMaxThread 个线程在运行
for(int i=0; i <nMaxThread; i++)
{
int val = GetPVal();

if( !val ){ continue; }

pTh[i].bDelete= NULL;
pTh[i].hThread = &hThread[i];
pTh[i].lVal = val;
hThread[i] = ::CreateThread(NULL,0,LPTHREAD_START_ROUTINE(&ClidThread),LPVOID( &pTh[i] ),0,NULL);
}


if( th->bDele…
[/Quote]

我在这里有设置值,只是起始值才为NULL

if( val )
{
th->bDelete = th->hThread ;
th->lVal = val;
th->hThread = ::CreateThread(NULL,0,LPTHREAD_START_ROUTINE(&ClidThread),LPVOID( th ),0,NULL);
}
子程子 2008-11-20
  • 打赏
  • 举报
回复
//创建几个子线程来运行,直到处理完所有数据为止,线程结束后自动判断是否再次创建线程来保存有 nMaxThread 个线程在运行
for(int i=0; i <nMaxThread; i++)
{
int val = GetPVal();

if( !val ){ continue; }

pTh[i].bDelete = NULL;
pTh[i].hThread = &hThread[i];
pTh[i].lVal = val;
hThread[i] = ::CreateThread(NULL,0,LPTHREAD_START_ROUTINE(&ClidThread),LPVOID( &pTh[i] ),0,NULL);
}



if( th->bDelete )
{
CloseHandle( th->bDelete );
th->bDelete = NULL;
}

你总是CLOSE的NULL啊。
就呆在云上 2008-11-20
  • 打赏
  • 举报
回复
还有:
你把这个改成:
long lWantP = 10; //待处理数据条数 

不用10000
你就可以看到
有很多线程没有执行,却被分配了句柄
明显不能被显式回收
因此,这里有两个建议:
1、建立的子线程可以自分离
2、new和delete是不是因为线程的不执行而不配对,那自然也会内存泄露
就呆在云上 2008-11-20
  • 打赏
  • 举报
回复
你内存泄露不是因为new和delete的问题把
是因为你的子线程没有回收
你只回收主线程的句柄
但是你貌似没有回收子线程的句柄,因为我觉得你的句柄的回收:
    //等所有线程结束
::WaitForMultipleObjects( nMaxThread,hThread,TRUE,INFINITE );

能回收所有子线程的句柄不?
建议你在创建子线程的时候使用分离属性
zhouqing19871024 2008-11-20
  • 打赏
  • 举报
回复
up
xhs_lh04 2008-11-20
  • 打赏
  • 举报
回复
UP
星羽 2008-11-20
  • 打赏
  • 举报
回复
delete [] pTh;
delete [] hThread;hThread = NULL;

的时候,有可能子线程还在使用
Non_Recursive 2008-11-20
  • 打赏
  • 举报
回复
不懂,up
Lnnu_lc 2008-11-20
  • 打赏
  • 举报
回复
顶了
帅得不敢出门 2008-11-20
  • 打赏
  • 举报
回复
帮up
spotatoes 2008-11-20
  • 打赏
  • 举报
回复
好像很难看,格式还退了



//
#include "stdafx.h"
#define _CRT_RAND_S
//
#include <windows.h>
#include <iostream>
using namespace std;

//
long lWantP = 100000; //待处理数据条数
int nMaxThread = 5; //分多少个线程来处理
HANDLE* hThread = NULL; //子线程句柄
HANDLE hMain = NULL; //主线程句柄

//
int GetPVal(void);
struct sctTh{
HANDLE bDelete; //保存子线程 自已创建线程时要CloseHandle的句柄
HANDLE hThread; //子线程本身执行的句柄
int lVal; //要处理的数据值,这里只做最简单的 整型处理
};

sctTh* pTh = NULL;
//
CRITICAL_SECTION g_cs = {0};
CRITICAL_SECTION o_cs = {0};

DWORD WINAPI ClidThread(LPVOID l)
{
sctTh* th = reinterpret_cast< sctTh* >( l );

if( !th ){ return 1; }
if( th->bDelete )
{
CloseHandle( th->bDelete );
th->bDelete = NULL;
}
::EnterCriticalSection( &o_cs );
cout<<" CT val: " << th->lVal <<endl;
::LeaveCriticalSection( &o_cs );
th->lVal++; //这里为了测试,只是简单+1后抛弃这个数据

int val = GetPVal();
if( val )
{
th->bDelete = th->hThread ;
th->lVal = val;
th->hThread = ::CreateThread(NULL,0,LPTHREAD_START_ROUTINE(&ClidThread),LPVOID( th ),0,NULL);
}
return 0;
}
//
DWORD WINAPI MainThread(LPVOID l)
{
hThread = new HANDLE[nMaxThread];
pTh = new sctTh [nMaxThread];
//

memset( pTh,0, sizeof(sctTh)*nMaxThread );
memset( hThread,0,sizeof(HANDLE)*nMaxThread);

//创建几个子线程来运行,直到处理完所有数据为止,线程结束后自动判断是否再次创建线程来保存有 nMaxThread 个线程在运行
for(int i=0; i<nMaxThread; i++)
{
int val = GetPVal();

if( !val ){ continue; }

pTh[i].bDelete = NULL;
pTh[i].hThread = &hThread[i];
pTh[i].lVal = val;
hThread[i] = ::CreateThread(NULL,0,LPTHREAD_START_ROUTINE(&ClidThread),LPVOID( &pTh[i] ),0,NULL);
}
//等所有线程结束
::WaitForMultipleObjects( nMaxThread,hThread,TRUE,INFINITE );
for( int i=0; i<nMaxThread; i++ )
{
CloseHandle( hThread[i] ); hThread[i] = NULL;
}

delete [] pTh;
delete [] hThread;hThread = NULL;
return 0;
}
//
int GetPVal(void)
{
int rel = 0;
::EnterCriticalSection( &g_cs );
if( lWantP > 0)
{
rel = lWantP-- ;
}
::LeaveCriticalSection( &g_cs );
return rel;
}
//
int _tmain(int argc, _TCHAR* argv[])
{
::InitializeCriticalSection( &g_cs );
::InitializeCriticalSection( &o_cs );
hMain = ::CreateThread(NULL,0,LPTHREAD_START_ROUTINE(&MainThread),LPVOID(0),0,NULL);
//if( !hMain ){ cout<<"Thread Create Failed !!"<<endl; }
::WaitForSingleObject(hMain,INFINITE);
Sleep(1000);
::DeleteCriticalSection( &g_cs );
::DeleteCriticalSection( &o_cs );
return 0;

}

65,211

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧