Question

My Code like this

starts is a array of DWORD32

threads is a array of HANDLE

void initThreads(HANDLE* threads, int size)
{
    DWORD32* starts = (DWORD32*)malloc(sizeof(DWORD32) * size);
    for (int i = 0; i < size; ++i)
    {
        starts[i] = num_steps / numThreads * i;
    }
    for (int i = 0; i < size; ++i)  
    {
        DWORD32* para = starts + i;
        printf("create %ld\n", *para);
        threads[i] = CreateThread(NULL, 0, portionCal, (void*)para, 0, NULL);
    }
    free(starts);
}

DWORD WINAPI portionCal(LPVOID pArg) 
{ 
   double x, portionSum = 0.0;
   DWORD32 start = *(DWORD32*)pArg;
   printf("start at %d\n", start);
}

But the result is

create 0
create 25000000
start at 0
create 50000000
create 75000000
start at 50000000
start at -17891602
start at 25000000

Why the result look like this?

Was it helpful?

Solution

We can't see the scope of starts but this can be guessed at from the failure. It is probably a local variable, long gone when the thread starts running. So you'll just read garbage. You'll need a stable pointer, get one from a global variable or malloc().

After edit: don't call free() like that. It has to remain stable until all threads have completed using it. You could consider reference counting it with InterlockedDecrement().

OTHER TIPS

You free the starts array immediately after creating the threads. So what happens is that the threads are passed pointers to memory that may have been freed before the threads have a chance to read it. If that happens, the resulting behaviour is undefined.

You can resolve the problem by ensuring that the memory referred to by the pointers has a lifetime that extends beyond that of the threads. Typically you do that by allocating off the heap the data for each thread, and letting the thread call free when it has taken a copy of the information.

In this case, the easier way to resolve the problem is to pass the integer value rather than a pointer to it. Like this:

threads[i] = CreateThread(NULL, 0, portionCal, (void*)starts[i], 0, NULL);

And in your thread:

DWORD32 start = (DWORD32)pArg;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top