Programar em C

Exercise 8: Desenvolver um programa designado ficha02exer08.c no qual são criados
inicialmente dois processos filho.
O primeiro processo irá escrever num ficheiro ficha02exer08-aleatory.dat, números aleatórios
localizados entre dois valores fornecidos ao programa através da linha de comando. A escrita
dos números deverá ser separada por 1s.
O segundo processo calculará recursivamente a média dos números produzidos e escreverá o
resultado no ficheiro ficha02exer08-recursive.dat. O cálculo deverá ser separado por 1s.
Também fornecida através da linha de comando será a duração total do programa. Quando este
tempo terminar o processo pai deverá criar o terceiro e quarto processos com a função indicada
em baixo e em seguida terminar.
O comando para correr o programa durante 10 s e considerando os valores entre 20 e 30 será:
./ ficha02exer08 10 20 30
A formula para calcular a média de forma recursiva é dada por:

seria este o enunciado de programaçao simples em C, mas agora tenho que utilizar threads para fazer o mesmo programa:
Deste modo, o programa original deve ser
melhorado de forma a incluir entre outras as seguintes funções:
- criação de threads;
- término de threads;
- joining de threads.


e tenho um problema, dá-me segmentation fault e nao percebo porque :/
Aqui vai o código:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
#include <time.h>
#include <math.h>


int linf;
int lsup;
int v=0;


void *thread_save_file(void *arg){
FILE * pFile;
float t=0.5;
srand ( time(NULL) );
lsup=lsup-linf;
while(1){
pFile = fopen ("aleatory.dat","a");
v = rand() % lsup + linf;
fprintf(pFile,"%i ", v);
fclose(pFile);
sleep(1);
}
pthread_exit(NULL);
}


void *thread_avg(void *arg){
FILE *pFile;
float t=0.5, avg, avg1;
int n = 1;
srand ( time(NULL) );
while(1){
pFile = fopen ("recursiveaverage.dat","a");
avg1 = avg1 * (n-1);
avg = (avg1 * (n-1) + v) / n;
fprintf(pFile,"%.2f ", avg);
n++;
fclose(pFile);

sleep(1);
}
pthread_exit(NULL);
}


int main (int argc, char **argv) {
int tempo,res;


tempo = atoi (argv[1]);
linf = atoi (argv[2]);
lsup = atoi (argv[3]);


pthread_t th1,th2;
void *thread_result;
pthread_create(&th1, NULL, thread_save_file, NULL);
pthread_create(&th2, NULL, thread_avg, NULL);
sleep(tempo);
pthread_cancel(th1);
pthread_cancel(th2);
printf("Programa executado com sucesso... confira os dados.\n");
pthread_join(th1, &thread_result);
pthread_join(th2, &thread_result);
}

se me puderem ajudar agradecia :/
 
Nunca ouviste falar do GDB? É uma óptima ferramenta para detectar segmentation faults. Aconselho a tentares utilizar e tentares descobrir por ti onde essa fuga acontece.
 
(gdb) run
Starting program: /home/marco/Documentos/Ficha 5/a.out
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".


Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7843f24 in ____strtoll_l_internal () from /lib64/libc.so.6
Missing separate debuginfos, use: debuginfo-install glibc-2.15-58.fc17.x86_64


aparece isto, o que devo fazer? nunca utilizei o gdb :/
 
Custa-me bastante a acreditar que estás "nesse nível" (threads, etc) e nunca usaste o gdb.
Normalmente o GDB costuma indicar exactamente a linha onde se dá o problema, coisa que não estou a ver nesse caso.

Uma ferramenta alternativa é o valgrind, que corres ./valgrind --leak-check=full ./ficha02exer08 10 20 30

Não esquecer: sempre que se faz o debug de um programa, este deve ser compilado com a flag -g ou -ggdb. Caso contrário o valgrind não te vai dar a linha onde recebeste o sinal SIGSEGV (Segmentation Fault) - sinceramente nem sei se o gdb funciona sem ser compilado com essa flag.

[EDIT] Hmmm... Confesso que já estou algo ferrugento com as threads, mas.... porque motivo estás a fazer pthread_cancel() e logo de seguida pthread_join()? Em principio estará aqui o problema: para deixar a thread correr ou fazes join ou fazes detach... não vais fazer um cancel e depois tentar fazer join a uma thread que supostamente mataste... Mas posso estar a confundir.

Cumps
 
Não esquecer: sempre que se faz o debug de um programa, este deve ser compilado com a flag -g ou -ggdb. Caso contrário o valgrind não te vai dar a linha onde recebeste o sinal SIGSEGV (Segmentation Fault) - sinceramente nem sei se o gdb funciona sem ser compilado com essa flag.

Sim, de facto esqueci-me de referir isso. Tens que compilar com a flag -g, ou seja, gcc -g -c ...

Tens aqui um cheat sheet para o gdb, é muito fácil.
http://darkdust.net/files/GDB%20Cheat%20Sheet.pdf
Se começares a utilizar vai te salvar horas de pancadaria nas paredes.
 
Back
Topo