3

I'm facing a weird problem. I have the below struct and the method that uses the struct.

struct AsyncData {
    string documentNo;
    string command;
    string filePath;
};
UINT AsyncDownloader(LPVOID pData) {
    AsyncData* ad = static_cast<AsyncData*>(pData);
    string cmd = ad->command;
    string path = ad->filePath;
    HRESULT hr = URLDownloadToFile(NULL, cmd, path, 0, NULL ); 
    if(SUCCEEDED(hr))
    {
        delete ad;
        return 0;
    }
    else
    {
        string val = ad->documentNo;
        return 1;
    }
}

The call comes from another method:

callerMethod()
{
    AsyncData* ad;
    ad = new (AsyncData);
    ad->filePath = filePath;
    ad->command = command;
    ad->documentNo = m_Target->SelectedDocNoList.GetString(i);
    AfxBeginThread(AsyncDownloader, (LPVOID)ad);
}

The problem is:

When the AsyncDownloader method gets called, the address of the struct sent and received is the same. But accessing the members, gives NULL values.

Any insights on what I'm doing wrong?

Jabberwocky
  • 48,281
  • 17
  • 65
  • 115
Siva Kumar
  • 41
  • 4
  • 1
    What about acessing members outside `AsyncDownloader`, does it also give `NULL` values? – PcAF Jul 01 '16 at 13:24
  • When I verify if the data is assigned to the AsyncData structure, YES, it has values. But, when the call comes to the method, even though the address is the same, after casting it back to struct, the members have NULL values, or some special symbols of the Unicode Characters... Still boggles me... – Siva Kumar Jul 01 '16 at 13:28
  • 1
    Hope this will help you http://stackoverflow.com/questions/16320354 – Csi Jul 01 '16 at 15:55
  • 2
    Put breakpoints, inspect the memory, look at the assembly code. – Jabberwocky Jul 01 '16 at 16:38
  • 1
    I think you need to use the primitive types in your struct. I think that when you pass a string its storage is stored in one thread and is not accessible from another. Try using char[xxx] for the struct elements – cha Jul 04 '16 at 05:30
  • 2
    Given all members of struct are string (I am assuming std::string, not a typedef of char*), I don't think you will get NULL. It could be a valid string or empty string, based on what you passed. Can you please provide statement which prints members ? – Amit Jul 04 '16 at 06:56
  • Posting the solution: struct AsyncData { int count; wchar_t filePath[250]; wchar_t command[250]; wchar_t docNo[20]; }; As @cha mentioned, the values should have been of primitive types. I copied the string values to wchar, using wcscpy_s. Then each thread could access the needed values by typecasting LPVOID* back to the structure*, and finally released the memory allocated for that structure. – Siva Kumar Jul 04 '16 at 13:54
  • 1
    @cha: That's complete bogus. All threads running in the same process share the same address space. All data is visible across all threads. Your "solution" merely masks another bug. And violates the [zero one infinity rule](https://en.wikipedia.org/wiki/Zero_one_infinity_rule). – IInspectable Jul 04 '16 at 20:27
  • 1
    [URLDownloadToFile](https://msdn.microsoft.com/en-us/library/ms775123.aspx) takes `LPCTSTR` as the second and third argument. Since your code passes `string`s and - presumably - compiles, means, that those `string`s aren't `std::string`s. What are they? – IInspectable Jul 04 '16 at 20:30
  • Second and Third arguments are of type, XString. – Siva Kumar Jul 05 '16 at 09:26
  • We do not know, what an `XString` is. It is not a Standard C++ class, nor is it part of MFC, or Windows. Without seeing the relevant parts and pieces there is no help to be had. Please provide a [mcve]. – IInspectable Jul 05 '16 at 13:47

0 Answers0