Ahoj,
pracuji na vícevláknové aplikaci a narazil jsem na problém v následujícím kódu. Funkce pocitej nedela vlastne nic jineho, nez ze zvetsi ukazatel o jednicku a precte z pole[ukazatel]. Je tam i semaphor, aby si vlákna nemohla měnit hodnotu data->ukazatel, ale i přesto to nefunguje.
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
sem_t mutex;
typedef struct DATA{
int ukazatel;
int ** pole;
} DATA;
void * pocitej(void * arg){
DATA * data = (DATA *) arg;
int * cislo;
while (1){
sem_wait(&mutex);
cislo = data->pole[data->ukazatel];
data->ukazatel = data->ukazatel + 1;
if (data->ukazatel > 100){
sem_post(&mutex);
break;
}
sem_post(&mutex);
}
return NULL;
}
void vlakna(int threads){
int ** pole = (int **)malloc(101 * sizeof(int *));
int i;
int * cislo;
pthread_t ** vlakna = (pthread_t **) malloc(threads * sizeof(pthread_t *));
pthread_attr_t attr;
sem_init(&mutex, 0, 1);
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
for (i = 0; i != 100; i++){
pole[i] = (int *) malloc(sizeof(int));
(*pole[i]) = i;
}
pole[i] = NULL;
DATA * data = (DATA *) malloc(sizeof(DATA));
data->ukazatel = 0;
data->pole = pole;
for (i = 0; i != threads; i++){
vlakna[i] = (pthread_t *) malloc(sizeof(pthread_t));
pthread_create(vlakna[i], &attr, pocitej, (void *) data);
}
for (i = 0; i != threads; i++){
pthread_join(*(vlakna[i]), NULL);
}
for (i = 0; i != 100; i++){
free(pole[i]);
}
free(pole);
for (i = 0; i != threads; i++){
free(vlakna[i]);
}
free(vlakna);
free(data);
pthread_attr_destroy(&attr);
}
int main(int argc, char *argv[]){
vlakna(5);
return 1;
}
Zkompiluju:
gcc -o a.out test.c -lpthread -lrt
spustím:
valgrind ./a.out
A výstup je:
==29337== Memcheck, a memory error detector
==29337== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al.
==29337== Using Valgrind-3.6.0.SVN-Debian and LibVEX; rerun with -h for copyright info
==29337== Command: ./a.out
==29337==
==29337== Thread 3:
==29337== Invalid read of size 8
==29337== at 0x4008DA: pocitej (in /home/jakub/prog/osy1/a.out)
==29337== Address 0x55d6368 is 0 bytes after a block of size 808 alloc'd
==29337== at 0x4C2815C: malloc (vg_replace_malloc.c:236)
==29337== by 0x400942: vlakna (in /home/jakub/prog/osy1/a.out)
==29337== by 0x400B66: main (in /home/jakub/prog/osy1/a.out)
==29337==
==29337==
==29337== HEAP SUMMARY:
==29337== in use at exit: 0 bytes in 0 blocks
==29337== total heap usage: 113 allocs, 113 frees, 2,664 bytes allocated
==29337==
==29337== All heap blocks were freed -- no leaks are possible
==29337==
==29337== For counts of detected and suppressed errors, rerun with: -v
==29337== ERROR SUMMARY: 4 errors from 1 contexts (suppressed: 4 from 4)
Všiml jsem si, že pokud upravím funkci pocitej:
...
if (data->ukazatel > 101-pocet_vlaken){
...
tak to funguje...
Kde je chyba
Děkuji