C 在Win32 API上将结构传递给线程时出现指针问题
用户提供用于计算分区数和线程数的命令行参数,其中每个线程对大型数组的特定分区进行最小线性搜索。线程找到的每个最小值都存储在一个小型全局数组中。然后,主函数对小数组进行最小线性搜索,同时对大数组进行最小搜索,并确认在小数组和大数组中找到的最小值相等。我遇到的问题是,小全局数组中的最小值有时是垃圾,有时与大数组中的最小值匹配。我试图找出这个问题,但似乎找不到。我们将非常感谢你的帮助。我正在用C编写代码,在win32 API上使用Dev-C++。代码如下:C 在Win32 API上将结构传递给线程时出现指针问题,c,multithreading,winapi,pointers,struct,C,Multithreading,Winapi,Pointers,Struct,用户提供用于计算分区数和线程数的命令行参数,其中每个线程对大型数组的特定分区进行最小线性搜索。线程找到的每个最小值都存储在一个小型全局数组中。然后,主函数对小数组进行最小线性搜索,同时对大数组进行最小搜索,并确认在小数组和大数组中找到的最小值相等。我遇到的问题是,小全局数组中的最小值有时是垃圾,有时与大数组中的最小值匹配。我试图找出这个问题,但似乎找不到。我们将非常感谢你的帮助。我正在用C编写代码,在win32 API上使用Dev-C++。代码如下: #include <inttypes.
#include <inttypes.h>
#include <stdlib.h>
#include <stdio.h>
#include <tchar.h>
#include <windows.h>
#define RAND_DIVISOR 800
int number_items = 0;
int size = 1;
int partits = 1;
int P = 0;
int N = 0;
int Index = 0;
int index_global = 0;
int min;
#define NUM_THREADS 65536 //or 2^16
typedef struct thread_data
{
int thread_id;
int a;
int b;
int * copy_array;
int * glob_array;
int nbr_items;
int subarraysize;
} s_param, *p_s_param;
int compare (const void *a, const void *b)
{
return( *(int*)a - *(int*)b);
}
DWORD WINAPI CompMin( LPVOID lpParam )
{
int i, tmp;
int SubArSize,nbrItems,thrid;
p_s_param param2;
param2 = (p_s_param)lpParam;
min = param2->copy_array[Index];
min = param2->copy_array[param2->a];
param2->glob_array[index_global] = min;
Index++;
index_global++;
}
int main(int argc, char *argv[])
{
int sub_array_size;
p_s_param pDataArray[NUM_THREADS];
DWORD dwThreadIdArray[NUM_THREADS];
HANDLE hThreadArray[NUM_THREADS];
HANDLE myhandle;
//pthread_t thID, thread;
p_s_param param[NUM_THREADS];
int rNum, rc = 0, i, j, large_min;
double time1, time2, time3, time4;
//get initial timestamp in micro seconds
struct timeval tv;
gettimeofday( &tv, NULL );
time1 = tv.tv_sec + ( tv.tv_usec / 1000000.0 );
printf( "Start timestamp: %f\n", time1 );
if(argc < 2 )
{
printf("Need %d arguments, only %d provided\n", 2, argc);
printf("The program will exit now!\n");
return 1;
}
P = atoi(argv[1]); /* will be used to define size of large array */
N = atoi(argv[2]); /* will be used to define number of threads */
if(N>P)
{
printf(" Argument 1 should be greater than argument 2\n");
printf("The program will exit now!\n");
return 1;
}
/*compute the size of the array*/
for (i=1; i<=P; i++)
size = size * 2;
/*Create a dynamic array of size size*/
int *array = (int*) malloc(size*sizeof(int));
srand(time(NULL));
for (i=0; i<size; i++)
{
rNum = rand() / RAND_DIVISOR;
array[i] = rNum;
}
/*compute the number of partitions*/
for (i = 1; i<=N; i++)
partits = partits * 2;
/*numbers of elements per sub array*/
sub_array_size = size/partits;
/*Global array*/
int *Globalarray = (int*) malloc(partits*sizeof(int));
for (i=0; i<partits; i++)
{
/*Allocate memory for thread data*/
param[i] = (p_s_param) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(s_param));
if( param[i] == NULL)
{
ExitProcess(2);
}
param[i]->a=i;
param[i]->copy_array=array;
param[i]->glob_array = Globalarray;
hThreadArray[i] = CreateThread(NULL, 0, CompMin, param[i], 0, &dwThreadIdArray[i]);
if(hThreadArray[i] == NULL)
{
puts("Error, cannot create Thread!");
puts(strerror(errno));
ExitProcess(3);
}
//printf("Number of partitions: %d\n",partits );
} WaitForMultipleObjects(NUM_THREADS,hThreadArray, TRUE, INFINITE);
/*find mimimum value from Global array returned by threads*/
min = Globalarray[0];
for(i = 0; i< partits; i++)
{
printf("Index: %d, value into small array: %d\n",i, Globalarray[i] );
if(Globalarray[i] < min)
min = Globalarray[i];
}
gettimeofday( &tv, NULL );
time2 = tv.tv_sec + ( tv.tv_usec / 1000000.0 );
gettimeofday( &tv, NULL );
time3 = tv.tv_sec + ( tv.tv_usec / 1000000.0 );
/*sorting the large array in ascending order and find minimum value*/
//qsort(array,size, sizeof(int), compare);
large_min = array[0];
for(i = 0; i< partits; i++)
{
printf("value into large array: %d\n",array[i] );
if(array[i] < large_min)
large_min = array[i];
}
//large_min = array[0];
gettimeofday( &tv, NULL );
time4 = tv.tv_sec + ( tv.tv_usec / 1000000.0 );
/*display result*/
printf("Min from small array : %d\n", min);
printf("Min from large array : %d\n", large_min);
if(min == large_min)
printf("Same minimum found in small and large array! : %d\n", large_min);
else
{
printf("error!, the min from small %d array is different from large array %d!\n", min, array[0]);
return 1;
}
printf("length of time recorded to search min in small array: %f\n", time2-time1);
printf("length of time recorded to search min in large array: %f\n", time4-time3);
free((void*) Globalarray);
free((void*) array);
exit (0);
}
#包括
#包括
#包括
#包括
#包括
#定义RAND_除数800
整数项=0;
int size=1;
int partits=1;
int P=0;
int N=0;
int指数=0;
int index_global=0;
int-min;
#定义NUM_线程65536//或2^16
typedef结构线程数据
{
int-thread_-id;
INTA;
int b;
int*copy_数组;
int*glob_数组;
国际nbr_项目;
int子阵列大小;
}s_参数,*p_s_参数;
整数比较(常数无效*a,常数无效*b)
{
返回(*(int*)a-*(int*)b);
}
DWORD WINAPI CompMin(LPVOID lpParam)
{
int i,tmp;
整数子大小,NBR项,三次;
p_s_param param2;
param2=(p_s_param)lpParam;
min=param2->复制数组[索引];
min=param2->copy_数组[param2->a];
参数2->全局数组[索引全局]=min;
索引++;
索引_global++;
}
int main(int argc,char*argv[])
{
int子数组大小;
p_s_参数pDataArray[NUM_THREADS];
DWORD DWTHREADIRAY[NUM_THREADS];
句柄hThreadArray[NUM_THREADS];
把手我的把手;
//pthread_t thID,thread;
p_s_param param[NUM_THREADS];
int rNum,rc=0,i,j,大_min;
双时间1,时间2,时间3,时间4;
//以微秒为单位获取初始时间戳
结构时间值电视;
gettimeofday(&tv,NULL);
time1=tv.tv\u sec+(tv.tv\u usec/1000000.0);
printf(“开始时间戳:%f\n”,time1);
如果(argc<2)
{
printf(“需要%d个参数,只提供了%d个”,2,argc);
printf(“程序将立即退出!\n”);
返回1;
}
P=atoi(argv[1]);/*将用于定义大数组的大小*/
N=atoi(argv[2]);/*将用于定义线程数*/
如果(N>P)
{
printf(“参数1应大于参数2\n”);
printf(“程序将立即退出!\n”);
返回1;
}
/*计算数组的大小*/
对于(i=1;i我在等待后添加了睡眠(3),它解决了问题。您的CompMin()
函数不是线程安全的。它正在访问由多个线程同时共享和修改的全局变量,因此当它们彼此并行运行时,它们将跨过彼此的数据。您需要使您的工作数据自包含,以便每个线程仅对其指定工作的数据进行操作,并且您设计的thread\u data
struct允许对数组数据进行分区,但实际上并没有利用该功能,因此每个线程都没有搜索其单独的数据分区,也没有将其搜索结果存储在全局数组的单独部分
您还将错误数量的线程句柄传递给了WaitForMultipleObjects()
,因此它将无法等待(您没有检查),然后在数组数据实际准备好处理之前继续处理它们
在线程完成运行后,您也会错误地搜索数组,因此最终不会得到正确的结果
请尝试类似以下内容:
#include <inttypes.h>
#include <stdlib.h>
#include <stdio.h>
#include <tchar.h>
#include <windows.h>
#define RAND_DIVISOR 800
typedef struct thread_data
{
DWORD thread_id;
int *items;
int nbr_items;
int min;
} s_thread_data, *p_s_thread_data;
/*
int compare (const void *a, const void *b)
{
return( *(int*)a - *(int*)b);
}
*/
DWORD WINAPI CompMin( LPVOID lpParam )
{
p_s_thread_data data = (p_s_thread_data) lpParam;
int i;
data->min = data->items[0];
for(i = 1; i < data->nbr_items; i++)
{
if(data->items[i] < data->min)
data->min = data->items[i];
}
return 0;
}
int main(int argc, char *argv[])
{
int size = 1;
int partits = 1;
int sub_array_size;
int i;
if(argc < 2 )
{
printf("Need %d arguments, only %d provided\n", 2, argc);
printf("The program will exit now!\n");
return 1;
}
int P = atoi(argv[1]); /* will be used to define size of large array */
if(P < 1)
{
printf(" Argument 1 should be greater than zero\n");
printf("The program will exit now!\n");
return 1;
}
int N = atoi(argv[2]); /* will be used to define number of threads */
if(N < 1)
{
printf(" Argument 2 should be greater than zero\n");
printf("The program will exit now!\n");
return 1;
}
/*compute the size of the large array*/
for (i=1; i<=P; i++)
size = size * 2;
/*Allocate memory for large array*/
int *array = (int*) malloc(size*sizeof(int));
if(array == NULL)
return 2;
srand(time(NULL));
/*Fill the large array with random data*/
for (i=0; i<size; i++)
array[i] = rand() / RAND_DIVISOR;
/*compute the number of partitions*/
for (i = 1; i<=N; i++)
partits = partits * 2;
//printf("Number of partitions: %d\n", partits );
/*numbers of elements per partition*/
sub_array_size = size/partits;
/*Allocate memory for thread data*/
p_s_thread_data ThreadDataArray = (p_s_thread_data) malloc(partits*sizeof(s_thread_data));
if(ThreadDataArray == NULL)
return 2;
memset(ThreadDataArray, 0, partits*sizeof(s_thread_data));
/*Allocate memory for thread handles array*/
HANDLE *hThreadArray = (HANDLE*) malloc(partits*sizeof(HANDLE));
if(hThreadArray == NULL)
return 2;
memset(hThreadArray, 0, partits*sizeof(HANDLE));
double time1, time2, time3, time4;
//get initial timestamp in micro seconds
struct timeval tv;
gettimeofday( &tv, NULL );
time1 = tv.tv_sec + ( tv.tv_usec / 1000000.0 );
printf( "Start timestamp: %f\n", time1 );
for (i=0; i<partits; i++)
{
ThreadDataArray[i].items = &array[i*sub_array_size];
ThreadDataArray[1].nbr_items = sub_array_size;
hThreadArray[i] = CreateThread(NULL, 0, CompMin, ¶m[i], 0, &(param[i].thread_id));
if(hThreadArray[i] == NULL)
{
printf("Error, cannot create Thread! %s\n", strerror(errno));
return 3;
}
}
/*Wait for threads to finish*/
i = 0;
int nbr_handles = partits;
while (nbr_handles >= MAXIMUM_WAIT_OBJECTS)
{
if (WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, &hThreadArray[i], TRUE, INFINITE) != WAIT_OBJECT_0)
return 4;
i = i + MAXIMUM_WAIT_OBJECTS;
nbr_handles = nbr_handles - MAXIMUM_WAIT_OBJECTS;
}
if (nbr_handles > 0)
{
if (WaitForMultipleObjects(nbr_handles, &hThreadArray[i], TRUE, INFINITE) != WAIT_OBJECT_0)
return 4;
}
/*find minimum value from thread results*/
int min = ThreadDataArray[0].min;
for(i = 0; i < partits; i++)
{
printf("Index: %d, value into small array: %d\n",i, ThreadDataArray[i].min );
if(ThreadDataArray[i].min < min)
min = ThreadDataArray[i].min;
}
gettimeofday( &tv, NULL );
time2 = tv.tv_sec + ( tv.tv_usec / 1000000.0 );
gettimeofday( &tv, NULL );
time3 = tv.tv_sec + ( tv.tv_usec / 1000000.0 );
/*sorting the large array in ascending order and find minimum value*/
//qsort(array,size, sizeof(int), compare);
int large_min = array[0];
for(i = 0; i < size; i++)
{
printf("value into large array: %d\n", array[i] );
if(array[i] < large_min)
large_min = array[i];
}
gettimeofday( &tv, NULL );
time4 = tv.tv_sec + ( tv.tv_usec / 1000000.0 );
/*display result*/
printf("Min from small array : %d\n", min);
printf("Min from large array : %d\n", large_min);
if(min == large_min)
printf("Same minimum found in small and large array! : %d\n", large_min);
else
{
printf("error!, the min from small array (%d) is different from large array (%d)!\n", min, large_min);
return 1;
}
printf("length of time recorded to search min in small array: %f\n", time2-time1);
printf("length of time recorded to search min in large array: %f\n", time4-time3);
free(array);
free(ThreadDataArray);
free(hThreadArray);
return 0;
}
#包括
#包括
#包括
#包括
#包括
#定义RAND_除数800
typedef结构线程数据
{
德沃德螺纹;
国际*项目;
国际nbr_项目;
int-min;
}s_线程数据,*p_s_线程数据;
/*
整数比较(常数无效*a,常数无效*b)
{
返回(*(int*)a-*(int*)b);
}
*/
DWORD WINAPI CompMin(LPVOID lpParam)
{
p_s_线程数据=(p_s_线程数据)lpParam;
int i;
数据->最小值=数据->项目[0];
对于(i=1;inbr\u项;i++)
{
if(数据->项目[i]min)
数据->最小值=数据->项目[i];
}
返回0;
}
int main(int argc,char*argv[])
{
int size=1;
int partits=1;
int子数组大小;
int i;
如果(argc<2)
{
printf(“需要%d个参数,只提供了%d个”,2,argc);
printf(“程序将立即退出!\n”);
返回1;
}
int P=atoi(argv[1]);/*将用于定义大数组的大小*/
if(P<1)
{
printf(“参数1应大于零\n”);
printf(“程序将立即退出!\n”);
返回1;
}
int N=atoi(argv[2]);/*将用于定义线程数*/
if(N<1)
{
printf(“参数2应大于零\n”);
printf(“程序将立即退出!\n”);
返回1;
}
/*计算大数组的大小*/
对于(i=1;i您可能需要在全局数组上进行某种同步。还要注意,WaitForMultipleObjects
一次最多只能等待64个句柄,而不是65536个。这个赋值说明我们不需要同步,因为每个线程将在特定分区上搜索最小值。index\u global
是所有线程共享的全局变量,那么您认为它们将如何避免冲突?我明白您的意思。我如何避免同步,但强制主线程等待每个线程完成?您是否还说在64个句柄之后可能会发生冲突?是否有任何方法将等待设置为65536?我的解决方案是线程的ace索引_全局