2016-03-25 3 views
0

Я просмотрел множество ответов здесь, где юбка вокруг моей проблемы, но никто не отвечает на проблему, с которой я столкнулся.Недопустимое использование выражения void с потоками (C)

Я кодирую многопоточную программу на C, которая выполняет умножение матрицы для оценки производительности системы.

В настоящее время я просто пытаюсь запустить один поток, передавая пару переменных.

Это мой код

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); 

И метод 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; 
} 

Всякий раз, когда я пытаюсь скомпилировать, я получаю ошибку «недопустимое использование пустого выражения» как на «Int начала» и "int end". Я основывал эти строки на the discussion found here. Любая помощь?

+0

Добро пожаловать в Переполнение стека. Обратите внимание, что предпочтительный способ сказать «спасибо» здесь ответы на вопросы и полезные ответы (если у вас достаточно репутации, чтобы сделать это), и, приняв наиболее полезный ответ на любой заданный вами вопрос (что также дает вам небольшой импульс для вашей репутации ). См. Страницу [About], а также [Как задать вопросы здесь?] (Http://stackoverflow.com/help/how-to-ask) и [Что мне делать, когда кто-то отвечает на мой вопрос ? ?] (http://stackoverflow.com/help/someone-answers) –

+0

Почему вы устанавливаете значения 'a' и' b' для значений return by 'malloc', а затем устанавливаете их на что-то еще, утечка выделенной памяти? –

ответ

2

Поскольку args является void *, вы не можете разыменования его, но args[0] делает попытку разыменования его перед нанесением (int *) литая. Таким образом, вы должны reparenthesize так void * преобразуется в int * перед вами разыменовать ней:

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

В качестве альтернативы (но то же самое):

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

Я не уверен, о &args в вызове pthread_create(). Это передает код void ***. Я думаю, что нужно что-то больше, как это, который имеет множество достоинств, включая быть проще:

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

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

Вы можете даже использовать:

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

Мне очень нравится простота кода, это действительно способ думать об этом. Но, поскольку это кажется трудным для понимания, часть внутри функции потока, возможно, также должна быть разработана. Что-то вроде 'int * bound = args', а затем доступ к' bound [0] '. –

+0

Это тот ответ, который я искал. Я не понимал, что круглые скобки нарушают разыменование. Кроме того, у меня на самом деле было что-то ближе к вашему второму блоку изначально, но я пытался заставить его работать на основе предыдущего вопроса, который я опубликовал.Спасибо, что пояснил этот бит. –

0

Я хотел написать комментарий об альтернативном подходе, чтобы сделать ваш код легче управлять, но это было долго ... так что подумайте об этом скорее в качестве совета, затем в ответ.

Начну с изучения некоторых проблем с вашим кодом, надеюсь, отвечая на исходный вопрос.

Затем я продемонстрирую альтернативный подход, используя struct. Этот альтернативный подход легче координировать и поддерживать с течением времени.

Ваш код имеет несколько проблем, которые могут привести к компиляции и выполнения ошибки, вот несколько примеров, которые должны указать вам правильный путь:

  1. Ваше int задание не выполняет то, что вы, возможно, хотел или предназначил его для выполнения.

    Ваш код присваивает числовое значение адреса указателя целому числу, возможно, обрезает данные из-за различий в размерах переменных. То, что вы, вероятно, хотели, было хранить указатель на int.

    Вы писали:

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

    Вы, вероятно, хотели написать:

    int * a = malloc(sizeof(int)); 
    int * b = malloc(sizeof(int)); 
    
  2. Ваш код обрабатывает void * как void ** (или int *) без использования каких-либо литья ...

    Вы писали:

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

    вероятно Вы имели в виду, чтобы написать:

    int start = ((int *)args)[0]; 
    int end = ((int *)args)[1]; 
    
  3. Ваш код выполняет malloc три (3) раза, но никогда не называет free (у вас есть утечка памяти).

Эти проблемы с орфографией чаще встречаются при попытке создания сложных структур данных вручную.

Было бы проще, если бы вы определили struct, чтобы содержать данные, которые вы хотели «переместить» в (или поделиться) с потоком.

Например, следующий непроверенного код, вероятно, не работает, но он четко показывает концепцию того, как с помощью передачи данных struct делает легче управлять, поддерживать и обновлять. Он также требует меньше вызовов 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; 
} 

Этот подход намного проще как для кодирования, так и для поддержания. Кроме того, когда вам нужно добавить данные для нового потока, это просто - просто обновите структуру.

Вы можете даже вернуть комплексные возвращаемые значения обратно в держатели места в структуре, позволяя потоку выполнять более сложные задачи (не забудьте избежать более одного потока, записывающего одно и то же поле struct).

+0

Я разговаривал с некоторыми одноклассниками, и они предлагали использовать структуру для передачи данных. Я мог бы использовать структуру, в дополнение к тому, о чем говорил другой комментатор. О, и я включил освобождение памяти, просто забыл включить его в свой блок кода. –

+0

@TNunn Я рад, что у вас есть вещи отсортированы. Я предполагаю, что ваш код запущен. Пожалуйста, не забудьте принять/проголосовать за любые ответы, которые вам помогли. Я вырвал ответ Джонатана Леффлера, я думаю, что это было так ... не так ли? – Myst

+0

На этом я попытался, но он сказал, что мне нужно 15 репутации, прежде чем мой подсчет голосов. Я просто сделал учетную запись. –

Смежные вопросы