Search code examples
multithreadingmfccstring

AfxBeginThread() + Cstring = garbage content


Please help me understand what is wrong with my code.

Header File

typedef void (*pStatusCallback)(UINT code, const CString& message);

class CComunicator
{
private:
    CUT_WSClient _client;
    bool _shouldTerminate;
    CString _serverAddress;
    UINT _serverPort;
    pStatusCallback _statusCallback;

    UINT _ThreadFunc();
    static UINT ThreadFunc(LPVOID pParam);
public:
    CComunicator(const CString& serverAddress, UINT serverPort, pStatusCallback statusCallback);
    ~CComunicator(void);

    void Start();
    void Stop();
}

Source file

CComunicator::CComunicator(const CString& serverAddress, UINT serverPort, pStatusCallback statusCallback) 
{
    _serverAddress = serverAddress;
    _serverPort = serverPort;
    _statusCallback = statusCallback;
}

CComunicator::~CComunicator(void)
{
}

void CComunicator::Start()
{
    _shouldTerminate = false;
    AfxBeginThread(CComunicator::ThreadFunc, this);
}

void CComunicator::Stop()
{
    _shouldTerminate = true;
}

UINT CComunicator::ThreadFunc(LPVOID pParam)
{
    return ((CComunicator*)pParam)->_ThreadFunc(); 
}

UINT CComunicator::_ThreadFunc()
{
    _statusCallback(0, _T("Connecting..."));
    _client.Connect(_serverPort, _serverAddress);
    _statusCallback(0, _T("Connected"));

    // do here some work


    _client.CloseConnection();

    return 0;
}

Usage

CComunicator com(_T("10.1.1.105"), 4502, ComunicatorCallback);
com.Start();

Why in method _ThreadFunc the _serverAddress contains garbage symbols? _serverPort has the correct value? Nobody else is altering the _serverAddress.

Thx for any ideas.


Solution

  • The bug is in the code you didn't paste, right after com.Start();. For example, if that function returns, com goes out of scope, taking the string out of scope too. Instead, do this:

    CComunicator *com=NEW CComunicator(_T("10.1.1.105"), 4502, CommunicatorCallback);
    
    com->Start();
    

    This will cause a memory leak, so you need to delete com; when you're done with it. The best way might be like this:

    UINT CComunicator::ThreadFunc(LPVOID pParam)
    {
        UNIT ret = ((CComunicator*)pParam)->_ThreadFunc(); 
        delete (CComunicator *)pParam;
        return ret;
    }
    

    Other possibilities include keeping the object in scope until you're sure the thread has terminated (if the thread that created the object can remain in that same scope until the object's thread is done) and reference counting the object, where the object's thread holds a reference to the object.