创建线程时遇到的问题:堆上和栈上的区别

cj1205 2010-06-18 04:45:10
m_hThread = CreateThread(NULL, 0, m_pThreadFunction, this, dwCreationFlags, &dwCreationFlags);

这段代码在堆上运行没有问题,但是在栈里面运行 m_hThread为NULL,谁知道为什么?
 int _tmain(int argc,char *argv[],char *envp[])
{
CSocketThread *threadone = new CSocketThread();
threadone->Start();
CSocketThread threadtwo;
threadtwo.Start(0);
system("pause");
return 0;
}

是否是生存期的问题?
...全文
252 18 打赏 收藏 转发到动态 举报
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
cj1205 2010-06-26
  • 打赏
  • 举报
回复
楼上说的有道理。。。我只考虑进程的创建,没考虑这个线程函数是这个类的成员函数,会有生命期的问题
cj1205 2010-06-25
  • 打赏
  • 举报
回复
#include "windows.h"
//=============================== Type Part ==================================//

class CBaseThread
{
public:
/** Constructor */
CBaseThread();
/** Destructor */
~CBaseThread();
public:
// 设置优先级
BOOL SetPriority(int priority);
// 获取优先级
int GetPriority();
// 挂起线程
DWORD Suspend();
// 还原线程
DWORD Resume();
// 开始跑
DWORD Start(DWORD dwCreationFlags = 0);
// 停止
DWORD Stop ( bool bForceKill = false);
DWORD Stop ( WORD timeout );

protected:
//子类必须实现,线程的具体方法
virtual DWORD ThreadMethod() = 0;
private:
//
static DWORD WINAPI CBaseThread::EntryPoint( LPVOID pArg);

protected:
LPTHREAD_START_ROUTINE m_pThreadFunction; //工作线程指针
BOOL m_bRunThread; //线程是否继续运行的标志
private:
HANDLE m_hThread; //Thread Handle 线程句柄
DWORD m_dwThreadID; //Thread ID 线程ID
LPVOID m_pParent; //pointer of the parent CThread object
DWORD m_dwExitCode; //Exit Code of the thread 线程退出码
};


//============================================================================//

//////////////////////////////// End of File ///////////////////////////////////




#include "BaseThread.h"

//------------------------------------------------------------------------------
// Method: CBaseThread
// Returns:
// Access: public
// Functionality: 构造函数
// Author : Vken.Chen
//------------------------------------------------------------------------------
CBaseThread::CBaseThread()
{
m_pThreadFunction = CBaseThread::EntryPoint;
m_bRunThread = FALSE;
}


//------------------------------------------------------------------------------
// Method: ~CBaseThread
// Returns:
// Access: virtual public
// Functionality: 析构函数
// Author : Vken.Chen
//------------------------------------------------------------------------------
CBaseThread::~CBaseThread()
{
if ( m_hThread )
Stop(true); //thread still running, so force the thread to stop!
}

//------------------------------------------------------------------------------
// Method: EntryPoint
// Returns: DWORD WINAPI
// Access: public static
// Parameter: LPVOID pArg
/* Functionality: DONT override this method.
this method is the "function" used when creating the thread. it is static so that way
a pointer to it is available inside the class. this method calls then the virtual
method of the parent class.
*/
// Author : Vken.Chen
//------------------------------------------------------------------------------
DWORD WINAPI CBaseThread::EntryPoint( LPVOID pArg)
{
CBaseThread *pParent = reinterpret_cast<CBaseThread*>(pArg);
pParent->ThreadMethod();//多态性,调用子类的实际工作函数
return 0;
}

//------------------------------------------------------------------------------
// Method: Start
// Returns: DWORD
// Access: public
// Parameter: DWORD dwCreationFlags,the flags to use for creating the thread.
// see CreateThread() in the windows sdk.
// Functionality: Starts the thread
// Author : Vken.Chen
//------------------------------------------------------------------------------
DWORD CBaseThread::Start(DWORD dwCreationFlags)
{
m_bRunThread = true;
m_hThread = CreateThread(NULL, 0, m_pThreadFunction, this, dwCreationFlags, &dwCreationFlags);
m_dwExitCode = GetLastError();
return m_dwExitCode;
}
cj1205 2010-06-25
  • 打赏
  • 举报
回复
//=============================== Include Files ================================
#include "stdio.h"
#include "stdlib.h"
#include <iostream>
using namespace std;

#include "winsock2.h"
#include "BaseThread.h"


//#pragma (lib,"ws2_32.lib")

//=============================== Type Part ====================================

class CSocketThread:public CBaseThread
{
protected:
//子类必须实现,线程的具体方法
DWORD ThreadMethod()
{
WSADATA wsaData;
int iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != NO_ERROR)
printf("Error at WSAStartup()\n");

//----------------------
// Create a SOCKET for connecting to server
m_hSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
if (m_hSocket == INVALID_SOCKET) {
printf("Error at socket(): %ld\n", WSAGetLastError());
WSACleanup();
return FALSE;
}

//----------------------
// The sockaddr_in structure specifies the address family,
// IP address, and port of the server to be connected to.
sockaddr_in clientService;
clientService.sin_family = AF_INET;
// clientService.sin_addr.s_addr = inet_addr( "127.0.0.1" );
clientService.sin_addr.s_addr = inet_addr( "192.168.18.67" );
// clientService.sin_addr.s_addr = inget_addr( "218.234.70.58" );
clientService.sin_port = htons( 60000 );
// clientService.sin_port = htons( 8090 );

//----------------------
// Connect to server.
if ( connect( m_hSocket, (SOCKADDR*) &clientService, sizeof(clientService) ) == SOCKET_ERROR) {
printf( "Failed to connect.\n" );
WSACleanup();
return FALSE;
}

//----------------------
// Declare and initialize variables.
int bytesSent;
int bytesRecv = 0;
char sendbuf[32] = "Client: Sending data.";
char recvbuf[32] = "";

//----------------------
// Send and receive data.
bytesSent = send( m_hSocket, sendbuf, strlen(sendbuf), 0 );
printf( "Bytes Sent: %ld\n", bytesSent );

while( bytesRecv != SOCKET_ERROR )
{
bytesRecv = recv( m_hSocket, recvbuf, 32, 0 );
DWORD dwError = GetLastError();
if ( bytesRecv == 0 || bytesRecv == WSAECONNRESET )
{
printf( "Connection Closed.\n");
break;
}
printf( "Bytes Recv: %ld\n %s\n", bytesRecv ,recvbuf );
}

WSACleanup();
return TRUE;
}
private:
SOCKET m_hSocket;
};

//==============================================================================

//=============================== Function Part ================================

void ThreadCreateOnStack()
{
WORD flag = 0;
CSocketThread testThread;
testThread.Start(flag);
int iRet = testThread.GetPriority();
testThread.Resume();
}
void ThreadCreateOnHeap()
{
WORD flag = 0;
CSocketThread *pTestThread = new CSocketThread();
pTestThread->Start(flag);
}

int _tmain(int argc,char *argv[],char *envp[])
{
ThreadCreateOnStack();
// ThreadCreateOnHeap();
system("pause");
return 0;
}


//==============================================================================
//////////////////////////////// End of File //////////////////////////////////
cj1205 2010-06-25
  • 打赏
  • 举报
回复
错误代码是126
而且我昨天蛮去测试了一下,发现栈上Create出来的线程有时候也能运行,只是概率比较低。
Antheus 2010-06-25
  • 打赏
  • 举报
回复
没有完整看完,只看到了这里:
void ThreadCreateOnStack()
{
WORD flag = 0;
CSocketThread testThread;
testThread.Start(flag);
int iRet = testThread.GetPriority();
testThread.Resume();
}
thread运行之后,testThread对象已经被销毁了,所以线程丢失了自己的地址空间,因为你的线程函数是依赖于类地址空间的,它的地址是在类地址空间的某处。不知道是否是这个问题引起的,但从当前情况来看,是的。
wolffan3150 2010-06-19
  • 打赏
  • 举报
回复
跟堆和栈上创建线程没有什么关系。只是你的CSocketThread对象的存储是在栈还是堆上,真正线程创建后还是在当前进程的地址空间内由进程统一管理,你的线程创建后并不属于任何一个CSocketThread对象,CSocketThread对象只扮演了一个线程创建者的身份而已,一旦创建后,在堆上和在栈上创建的线程没有任何区别。线程的堆栈地址空间仍然是由系统从当前进程的地址空间分配的。
Antheus 2010-06-19
  • 打赏
  • 举报
回复
哦,对了。
尽量用AfxBeginThread或_beginthreadx,尽量别用CreateThread。
对ErrorNo值的影响是CreateThread最明显的弊端。
Antheus 2010-06-19
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 cj1205 的回复:]
6楼的兄弟说的有道理,可是为什么我的程序会出现这种情况呢?
[/Quote]

其实类似于CreateThread这类的函数很少会出现返回NULL,就是说创建线程不成功的情况。多贴点代码出来或者自己进一步用GetLastError看看错误代码。
yfxucn 2010-06-18
  • 打赏
  • 举报
回复
轻轻地我走了正如我轻轻地来`~
zxdyu2009 2010-06-18
  • 打赏
  • 举报
回复
楼主,不会是NULL的这两种,你类CSocketThread类代码帖出来。
vincent_1011 2010-06-18
  • 打赏
  • 举报
回复
用messagebox来hold下
cj1205 2010-06-18
  • 打赏
  • 举报
回复
6楼的兄弟说的有道理,可是为什么我的程序会出现这种情况呢?
Antheus 2010-06-18
  • 打赏
  • 举报
回复
楼主是不是找到自己程序问题所在了?
以我的理解来看,这个跟堆和栈上创建线程没有什么关系。只是你的CSocketThread对象的存储是在栈还是堆上,真正线程创建后还是在当前进程的地址空间内由进程统一管理,你的线程创建后并不属于任何一个CSocketThread对象,CSocketThread对象只扮演了一个线程创建者的身份而已,一旦创建后,在堆上和在栈上创建的线程没有任何区别。线程的堆栈地址空间仍然是由系统从当前进程的地址空间分配的。
wangli820 2010-06-18
  • 打赏
  • 举报
回复
主线程退出,对象就没了。。。,m_hThread也被释放了
cj1205 2010-06-18
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 bit_maidong 的回复:]

主线程退出,对象就没了。。。,m_hThread也被释放了
[/Quote]
system("pause");在这之前主线程应该还没退出吧
bit_maidong 2010-06-18
  • 打赏
  • 举报
回复
主线程退出,对象就没了。。。,m_hThread也被释放了
cj1205 2010-06-18
  • 打赏
  • 举报
回复
同一段代码啊,只是一个声明在栈上,一个在堆上。CSocketThread *threadone = new CSocketThread();
与 CSocketThread threadtwo;
Eleven 2010-06-18
  • 打赏
  • 举报
回复
为NULL,CreateThread创建线程失败???

15,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 进程/线程/DLL
社区管理员
  • 进程/线程/DLL社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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