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;
}
是否是生存期的问题?

解决方案 »

  1.   

    为NULL,CreateThread创建线程失败???
      

  2.   

    同一段代码啊,只是一个声明在栈上,一个在堆上。CSocketThread *threadone = new CSocketThread();
    与 CSocketThread threadtwo;
      

  3.   

    主线程退出,对象就没了,m_hThread也被释放了
      

  4.   

    system("pause");在这之前主线程应该还没退出吧
      

  5.   

    主线程退出,对象就没了,m_hThread也被释放了
      

  6.   

    楼主是不是找到自己程序问题所在了?
    以我的理解来看,这个跟堆和栈上创建线程没有什么关系。只是你的CSocketThread对象的存储是在栈还是堆上,真正线程创建后还是在当前进程的地址空间内由进程统一管理,你的线程创建后并不属于任何一个CSocketThread对象,CSocketThread对象只扮演了一个线程创建者的身份而已,一旦创建后,在堆上和在栈上创建的线程没有任何区别。线程的堆栈地址空间仍然是由系统从当前进程的地址空间分配的。
      

  7.   

    楼主,不会是NULL的这两种,你类CSocketThread类代码帖出来。
      

  8.   


    其实类似于CreateThread这类的函数很少会出现返回NULL,就是说创建线程不成功的情况。多贴点代码出来或者自己进一步用GetLastError看看错误代码。
      

  9.   

    哦,对了。
    尽量用AfxBeginThread或_beginthreadx,尽量别用CreateThread。
    对ErrorNo值的影响是CreateThread最明显的弊端。
      

  10.   

    跟堆和栈上创建线程没有什么关系。只是你的CSocketThread对象的存储是在栈还是堆上,真正线程创建后还是在当前进程的地址空间内由进程统一管理,你的线程创建后并不属于任何一个CSocketThread对象,CSocketThread对象只扮演了一个线程创建者的身份而已,一旦创建后,在堆上和在栈上创建的线程没有任何区别。线程的堆栈地址空间仍然是由系统从当前进程的地址空间分配的。
      

  11.   

    错误代码是126
    而且我昨天蛮去测试了一下,发现栈上Create出来的线程有时候也能运行,只是概率比较低。
      

  12.   

    //=============================== 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 //////////////////////////////////
      

  13.   

    #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;
    }
      

  14.   

    没有完整看完,只看到了这里:
    void ThreadCreateOnStack()
    {
        WORD flag = 0;
        CSocketThread testThread;
        testThread.Start(flag);    
        int iRet = testThread.GetPriority();
        testThread.Resume();
    }
    thread运行之后,testThread对象已经被销毁了,所以线程丢失了自己的地址空间,因为你的线程函数是依赖于类地址空间的,它的地址是在类地址空间的某处。不知道是否是这个问题引起的,但从当前情况来看,是的。