简体   繁体   English

无效使用void表达式与线程(C)

[英]Invalid use of void expression with threads (C)

I've looked through tons of answers on here that skirt around my issue, but none answer the problem I am facing. 在这里,我已经浏览了无数答案,而这些答案都绕过我的问题,但没有一个答案能解决我面临的问题。

I am coding a multi-threaded program in C that does matrix multiplication to evaluate system performance. 我正在用C编写一个多线程程序,该程序执行矩阵乘法以评估系统性能。

Currently I am simply trying to start a single thread while passing in a couple variables. 目前,我只是试图在传递几个变量的同时启动一个线程。

This is my code 这是我的代码

pthread_t *thread = (pthread_t *) malloc(sizeof(pthread_t));

int a = malloc(sizeof(int));
int b = malloc(sizeof(int));
a = 0;
b = size;
void **args = (void **) malloc(2 * sizeof(void *));
args[0] = (void *)a;
args[1] = (void *)b;

pthread_create(&thread[0], NULL, matrixMath, &args);

And the matrixMath method: 和matrixMath方法:

void* matrixMath(void* args) {
  int start = *((int *)args[0]);
  int end = *((int *)args[1]);

  printf("Start: %d, End: %d\n", start, end);

  return NULL;
}

Whenever I try to compile, I get an "invalid use of void expression" at both the "int start" and "int end" declarations. 每当我尝试编译时,在“ int start”和“ int end”声明中都会得到“无效使用void表达式”。 I based those lines on the discussion found here . 我将这些内容基于此处的讨论 Any help? 有什么帮助吗?

Since args is a void * , you can't dereference it, but args[0] does attempt to dereference it before the (int *) cast is applied. 由于args是一个void * ,因此您不能取消引用它,但是args[0]确实会在应用(int *)强制转换之前尝试对其进行引用。 So, you need to reparenthesize so the void * is converted to an int * before you dereference it: 因此,您需要重新确定大小,以便在取消引用之前将void *转换为int *

int start = ((int *)args)[0];
int end   = ((int *)args)[1];

Alternatively (but equivalently): 或者(但等效):

int *array = (int *)args;  // You could skip the cast in C
int start  = args[0];
int end    = args[1];

I'm not convinced about &args in the call to pthread_create() either. pthread_create()的调用中,我也不相信&args That passes a void *** to the thread code. 这会将void ***传递给线程代码。 I think you need something more like this, which has multiple merits including being simpler: 我认为您需要更多类似这样的东西,它具有多个优点,包括更简单:

pthread_t thread;
int *a = malloc(2 * sizeof(int));
a[0] = 0;
a[1] = size;

pthread_create(&thread, NULL, matrixMath, a);

You could even use: 您甚至可以使用:

pthread_t thread;
int a[] = { 0, size };
pthread_create(&thread, NULL, matrixMath, a);

I'm going to demonstrate an alternative approach, using a struct . 我将使用struct演示另一种方法。 This alternative approach is easier to both code and maintain over time. 随着时间的推移,这种替代方法更易于编码和维护。

Your code has a few issues that might cause compiler and runtime errors, here are a few examples that should point you to the right path: 您的代码中存在一些可能导致编译器和运行时错误的问题,以下是一些示例,应为您指明正确的路径:

  1. Your int assignment isn't performing what you might have wanted or intended it to perform. 您的int作业没有执行您可能想要或想要执行的任务。

    Your code assigns the numerical value of a pointer's address to an integer, probably truncating the data due to variable size differences... What you probably wanted was to store a pointer to an int. 您的代码将指针地址的数值分配给整数,由于大小可变而可能会截断数据……您可能想要的是存储指向int的指针。

    You wrote: 你写了:

     int a = malloc(sizeof(int)); int b = malloc(sizeof(int)); 

    You probably meant to write: 您可能打算写:

     int * a = malloc(sizeof(int)); int * b = malloc(sizeof(int)); 
  2. Your code is treating void * as a void ** (or int * ) without using any casting... 您的代码将void *视为void ** (或int * ),而不使用任何强制转换...

    You wrote: 你写了:

     int start = *((int *)args[0]); int end = ((int *)args)[1]; 

    You probably meant to write: 您可能打算写:

     int start = ( (int *)args )[0]; int end = ( (int *)args )[1]; 
  3. Your code performs malloc three (3) times, but never calls free (you have a memory leak). 您的代码执行malloc三(3)次,但永远不会调用free (内存泄漏)。

It would be easier if you defined a struct to contain the data you wanted to "move" to (or share with) the thread. 如果定义一个struct以包含要“移动”到线程(或与线程共享)的数据,将会更容易。

For example, the following untested code probably doesn't work, but it clearly show the concept of how using a struct makes data transfer easier to manage, maintain and update. 例如,以下未经测试的代码可能无法工作,但它清楚地说明了使用struct如何使数据传输更易于管理,维护和更新的概念。 It also requires less calls to malloc , making memory management easier. 它还需要更少的对malloc调用,从而使内存管理更加容易。

struct ThreadData {
   int start;
   int end;
};

void * thread_task(void *);

int main(void) {
   struct ThreadData * data = malloc(sizeof(*data));
   data->start = 0;
   data->end = 0; // = size;
   pthread_t thr;
   pthread_create(&thr, NULL, thread_task, data);
   // ... do whatever.
   // ... remember to join thread
}

void * thread_task(void * _data) {
   struct ThreadData * data = _data;
   printf("Start: %d, End: %d\n", data->start, data->end);
   // remember to free the memory when you're done.
   free(data);
   return NULL;
}

This approach is much easier to both code and maintain. 这种方法更易于编码和维护。 Also, when you need to add data for the new thread, it's easy - just update the struct. 另外,当您需要为新线程添加数据时,这很容易-只需更新结构即可。

You can even put complex return values back into place-holders in the struct, allowing the thread to perform more complex tasks (remember to avoid having more than a single thread writing to the same struct field). 您甚至可以将复杂的返回值放回结构中的占位符,以允许线程执行更复杂的任务(请记住,避免有多个线程向同一struct字段写入数据)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM