-1

我的代码是这样的

starts是一个数组DWORD32

threads是一个数组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);
}

但结果是

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

为什么结果看起来像这样?

4

2 回答 2

2

我们看不到启动的范围,但这可以从失败中猜到。它可能是一个局部变量,在线程开始运行时早已消失。所以你只会读垃圾。您需要一个稳定的指针,从全局变量或 malloc() 中获取一个。

编辑后:不要那样调用 free() 。它必须保持稳定,直到所有线程都完成使用它。您可以考虑使用 InterlockedDecrement() 对其进行引用计数。

于 2013-11-27T15:30:21.430 回答
1

starts创建线程后立即释放数组。所以发生的事情是线程被传递了指向内存的指针,这些内存可能在线程有机会读取它之前就被释放了。如果发生这种情况,则结果行为是未定义的。

您可以通过确保指针引用的内存的生命周期超出线程的生命周期来解决此问题。通常,您通过在堆中为每个线程分配数据,并free在获取信息副本时让线程调用来做到这一点。

在这种情况下,解决问题的更简单方法是传递整数值而不是指向它的指针。像这样:

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

在你的线程中:

DWORD32 start = (DWORD32)pArg;
于 2013-11-27T15:36:44.763 回答