c - Why cant I cast a void* back to an int* and dereference it?
问题描述
Im trying to understand threading in C from a lab from my teacher and this is the way he had us do it in class.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <pthread.h>
#define numberlen 1000000
int sum = 0;
int arr[numberlen];
void* Summing(void* param)
{
int n = *((int*)param); //I'm guessing this is where my issue is but I'm still a first year so i'm not sure.
int base = 500000 * n;
for(int i =0; i<500000;i++)
{
sum += arr[i+base];
}
}
int main()
{
int nonthreadsum = 0;
pthread_t thread_id_first;
pthread_t thread_id_second;
srand(time(NULL));
for(int i = 0; i<numberlen;i++)
{
int r = (rand() % 10);
arr[i] = r;
nonthreadsum += r;
}
printf("%d\n",nonthreadsum);
pthread_create(&thread_id_first, NULL, Summing, (void*)0);
pthread_create(&thread_id_second, NULL, Summing, (void*)1);
printf("%d\n", sum);
return 1;
}
The issue I keep running into is that pthread functions only allow void*'s as arguments to pass to the actual function to be run. Otherwise I'd just put 0 or 1 in as the argument. If anyone knows a way around this i'd appreciate it.
解决方案
It's allowed (in some cases) to cast from an integer to a pointer and from a pointer to an integer. The problem is that's not what you're attempting to do.
When you call pthread_create
, you're casting the integer values 1
and 0
to type void *
. This is fine. But then in the thread function you do this:
int n = *((int*)param);
You cast the void *
argument to int *
and then attempt to dereference that pointer. But you didn't pass in an int *
. You passed an int
. So your program is treating the values 1 and 0 as pointers (the latter of which is actually a NULL pointer).
Since you converted from int
to void *
when you passed the values to the function, you want to cast back to int
inside of the function.
int n = (int)param;
That being said, the best way to handle this would be to pass an actual int *
to the function and convert it back in the function. Converting from an int *
to a void *
and back is well defined in all cases.
You can do this by defining variables in the main
function to dynamically create memory to hold these values:
int *t1_val = malloc(sizeof(*t1_val));
int *t2_val = malloc(sizeof(*t2_val));
*t1_val = 0;
*t2_val = 1;
pthread_create(&thread_id_first, NULL, Summing, t1_val);
pthread_create(&thread_id_second, NULL, Summing, t2_val);
Then using them in the thread as you were, adding a call to free
:
int n = *((int*)param);
free(param);
You could also do this without dynamic allocation by using variables of type int
and passing their address, but you would need to make sure those variables don't go out of scope by the time the thread attempts to dereference the pointer.
推荐阅读
- android - 在 Progressive Web App 上可以进行屏幕旋转,但在 Native android 应用程序上则不行
- amazon-web-services - Apache Airflow S3ListOperator 未列出文件
- java - SAX Parser 不显示多个相同的标签
- json - 使用 jq 将 JSON 文档中的单个 JSON 对象转换为数组
- reactjs - 如果我的前端在生产中崩溃,Chrome 会显示什么?
- github - 如何将整个分支移动到主分支
- sql - MS Access SQL 的每周趋势图
- node.js - Pulumi 文件存档 - 没有这样的文件或目录
- python - Matplotlib 异常轴值
- python - 使用 if 语句通过 python 发送电子邮件