Problem: Implement a program that gets as arguments a file name followed by words. For each word, create a separate thread that counts its appearances in the given file.Print out the sum of the appearances of all words.
Below I did a code but I receive : Segmentaion Fault (core dumped) when I run it.
PS: I do not know if the code is correct and does the requirement succesfully
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
pthread_mutex_t mtx;
int sum = 0;
char filename[10];
char word[10];
void * voidCount(void* p){
char cmd[100], appearences[100];
FILE *f;
sprintf(cmd, "echo %s | grep -o %s | wc -l", filename, word);
f = popen(cmd, "r");
fgets(appearences, sizeof(int), f);
pthread_mutex_lock(&mtx);
sum += *((int*)appearences);
pthread_mutex_unlock(&mtx);
return NULL;
}
int main(int argc, char *argv[]){
pthread_mutex_init(&mtx, NULL);
pthread_t threads[argc-1];
int i = 0;
for ( i = 1; i < argc-1; i++){
strcpy(filename, argv[1]);
strcpy(word, argv[i]);
pthread_create(&threads[i], NULL, voidCount, NULL);
}
for (i = 0; i < argc-1; ++i){
pthread_join(threads[i], NULL);
}
printf("Total appearences: %d", sum);
pthread_mutex_destroy(&mtx);
return 0;
}
The program has to complete few tasks in order to solve the problem:
set the number of threads depending on the number of words to search for
properly allocate and initialize thread arguments
pass each individual word as individual thread argument
protect shared variables during computation
get the results
Here's a minimal functional demo rework of your code with few essential comments. Word search is case sensitive.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
pthread_mutex_t mtx;
int sum = 0;
char filename[10]; //declared global for simplicity
//we search all the words in the same file
void * voidCount(void* p){
char *word, cmd[100], appearences[100];
int num;
FILE *f;
word = ((char*)p);
printf ("word : %s\n",word);
sprintf(cmd, "more %s | grep -o %s | wc -l", filename, word);//echo didn't work
printf ("%s\n",cmd); //debug print
pthread_mutex_lock(&mtx);
f = popen(cmd, "r");
if(fgets(appearences, sizeof(appearences), f) == NULL)
printf("Pipe error\n"); //better error handling is welcome...
printf("Appearances of \"%s\": %s\n", word, appearences);
num = atoi(appearances); //convert string to int
sum += num;
pclose(f); //close pipe
pthread_mutex_unlock(&mtx);
return NULL;
}
int main(int argc, char *argv[])
{
pthread_mutex_init(&mtx, NULL);
pthread_t threads[argc-1];
char **data = calloc(argc,sizeof(char*)); // initialize thread data
int i = 0;
strcpy(filename, argv[1]);
for ( i = 2; i < argc; i++){
data[i-2] = calloc(33, sizeof(char));//let's allow for somewhat longer words
strcpy(data[i-2], argv[i]);
strcat(data[i-2], "\0");
pthread_create(&threads[i-2], NULL, voidCount, data[i-2]);//each word a thread arg
}
for (i = 0; i < argc-1; ++i){;
pthread_join(threads[i], NULL);
}
printf("Total appearences: %d\n", sum);
pthread_mutex_destroy(&mtx);
for (i = 0; i < argc; i++)//free thread data
free (data[i]);
free (data);
return 0;
}
Hope this can help.
Related
I am trying to create a thread that can read the number of lines in a file when called from main.c
main.c
#include <stdio.h>
#define MAX_FILE_NAME 100
#include "t_func.h"
#include <pthread.h>
int main(){
int linecount;
pthread_t thread_id;
FILE *fh = fopen("/home/usr154/out.log", "r");
pthread_create(&thread_id, NULL, count_lines,&fh);
pthread_join(thread_id, (void **) linecount);
printf("lines: %d \n", linecount);
}
t_func.h
#include <stdlib.h>
#include <stdio.h>
int count_lines(int *fh){
char c;
int count =0;
if (fh == NULL)
{
printf("Could not open file %s", fh);
return 0;
}
for (c = getc(fh); c != EOF; c = getc(fh))
if (c == '\n')
count++;
fclose(fh);
return count;
}
I am facing 2 problems (or more), file pointer not being accepted and the return value not being handled, any help is much appreciated (I am new to C programming).
MAX_FILE_NAME was not used.
Manage resource in same scope. I choose to do in main() here which in this case include fopen(), error check, and fclose()
Changed signature on *count_lines() to match what pthread_create() expects.
Changed type of c from char to int.
Changed behavior to take file on command line to avoid having to create the file that code expects.
I am getting a warning warning: cast to pointer from integer of different size for return (void *) count; with gcc -Wall -Wextra. Is there a better way to return a value? Other than global variable, pass in arg with an out parameter for the value, or allocating something in the thread.
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
void *count_lines(void *arg) {
FILE *fh = (FILE *) arg;
int c;
int count = 0;
while((c = getc(fh)) != EOF) {
if(c == '\n') count++;
}
return (void *) count;
}
int main(int argc, char *argv[]) {
pthread_t thread_id;
if(argc != 2) {
printf("usage: %s path_of_flie\n", argv[0]);
return 1;
}
FILE *fh = fopen(argv[1], "r");
if(!fh) {
printf("Could not open file %s", argv[1]);
return 1;
}
pthread_create(&thread_id, NULL, count_lines, fh);
int linecount;
pthread_join(thread_id, (void **) &linecount);
fclose(fh);
printf("lines: %d \n", linecount);
}
and running the program on itself it returns:
lines: 32
//trying to make each thread print its thread number not id and then print a message from the array would like to be able to pass array in pthread create but right now I am getting a an error array subscript is not an integer please help me
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <pthread.h>
void * print_funtion( void* i, void* message)
{
printf("Thread %d: ",(int*) i);
printf("Thread %s: ", message);
return NULL;
}
int main(int argc, char* argv[]){
int i;
int num = atoi(argv[1]);
//printf("%d \n", num);
for(i = 1; i <= num; i++)
{
char *messages[] = {"Hello", "Bonjour", "Hola", "Shalom", "Namaste", "Gutan Tag", "God dag","Ola", "Salut", "Napot", "Dia"};
//printf("%d \n", i);
pthread_t tid;
pthread_create(&tid, NULL, print_funtion,(void*)i, (void*)messages[i]);
pthread_join(tid,NULL);
}
return 0;
}
There are many problems in the code and I'll point them out individually as comments:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <pthread.h>
// Note: In most cases, you should use (char *) for strings instead of char[XX].
// Note: You don't need to set the number of elements in the array
// because it is automatically inferred from the initializer.
char *messages[] = {"Hello", "Bonjour", "Hola", "Shalom", "Namaste", "Gutan Tag", "God dag","Ola", "Salut", "Napot", "Dia"};
void *print_function(void *data)
{
// The data you passed is int not a pointer to int.
int i = (int)data;
printf("Thread %d: \n", i);
// You need to use %s for printing string.
printf("Message: %s\n", messages[i]);
return NULL;
}
int main(int argc, char* argv[])
{
int i;
int num = atoi(argv[1]);
// Limit the number of running threads so you don't slow down you computer (10 is already too much. It depends on the number of cores you CPU has).
#define MAX_NUM_OF_THREADS 10
if(num > MAX_NUM_OF_THREADS)
num = MAX_NUM_OF_THREADS;
// I explain why we need to store the thread ids down below.
pthread_t thread_ids[MAX_NUM_OF_THREADS];
for(i = 0; i < num; i++)
{
pthread_t tid;
void *thread_data = (void *)(i + 1);
pthread_create(&tid, NULL, print_function, thread_data);
thread_ids[i] = tid;
}
// You can't join with the thread in the previous loop because it will serialize thread creation.
// Meaning the program will not create the next thread before the current thread finish execution.
// Instead, you need to create all the threads first then you join to them one by one afterward.
// And for that you need to store the thread ids for each thread in order to join with them after they are created.
for(i = 0; i < num; i++)
{
pthread_join(thread_ids[i], NULL);
}
return 0;
}
My program's desired functionality:
Using the command line user inputs N and M. N is the number of new threads that will be created and M is the number of how much every thread increments the global variable A.
This is my code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
static int A = 0;
void *Thread(void* x){
int i;
int n = *((int*)x);
for (i = 0; i<n; i++){
A++;
}
}
int main(int argc, char* argv[]){
int i;
int N = atoi(argv[1]);
int M = atoi(argv[2]);
pthread_t *thread = (pthread_t *) malloc(sizeof(pthread_t)*N);
if(!thread){
printf("No memory\n");
exit(2);
}
for (i = 0; i< N; i++){
if (pthread_create(&thread[i], NULL, Thread, &M)){
printf("Not able to create a thread\n");
exit(1);
}
}
for(i = 0; i< N; i++)
pthread_join(thread[i], NULL);
printf("A = %d\n", A);
return 0;
}
The problem is that every time I run it there's a different output.
Screenshot of my terminal when i run the program multiple times in a row
The problem is that you are creating multiple threads that in parallel are trying to modify your static A global variable at the same time, without any kind of protection.
That means that depending on the scheduling of the threads, the changes on your global variable will not be atomic, producing this effect.
You can solve this with a mutex, declare it with:
pthread_mutex_t mutex;
And initialise / release it with pthread_mutex_init and pthread_mutex_destroy.
Inside of the thread, before doing the change protect the resource to change with pthread_mutex_lock, and release it with pthread_mutex_unlock. So the code will be changed like this:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
static int A = 0;
pthread_mutex_t mutex;
void *Thread(void* x){
int i;
int n = *((int*)x);
pthread_mutex_lock(&mutex);
A += n;
pthread_mutex_unlock(&mutex);
}
int main(int argc, char* argv[]){
int i;
int N = atoi(argv[1]);
int M = atoi(argv[2]);
pthread_mutex_init(&mutex, NULL);
pthread_t *thread = (pthread_t *) malloc(sizeof(pthread_t)*N);
if(!thread){
printf("No memory\n");
exit(2);
}
for (i = 0; i< N; i++){
if (pthread_create(&thread[i], NULL, Thread, &M)){
printf("Not able to create a thread\n");
exit(1);
}
}
for(i = 0; i< N; i++)
pthread_join(thread[i], NULL);
printf("A = %d\n", A);
pthread_mutex_destroy(&mutex);
return 0;
}
I have written the code below but when I run it it brings segmentation fault. It compiles correctly though. Where are my mistakes?
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
static int N = 5;
static void* run(void *arg) {
int *i = (int *) arg;
char buf[123];
snprintf(buf, sizeof(buf), "thread %d", *i);
return buf;
}
int main(int argc, char *argv[]) {
int i;
pthread_t *pt = NULL;
for (i = 0; i < N; i++) {
pthread_create(pt, NULL, run, &i);
}
return EXIT_SUCCESS;
}
Any hint is welcomed.
Thank you
You have serveral issues:
1) You are passing a NULL to pthread_create() which is probably the reason for segfault.
2) You don't wait for the threads to complete (when main thread exits the whole process dies).
3) You are passing the address same variable i to all threads. This is a data race.
4) You are returning the address of a local variable buf from the thread function.
You can fix it like:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
static int N = 5;
static void* run(void *arg) {
int *i = (int *) arg;
char *buf = malloc(16);
snprintf(buf, 16, "thread %d", *i);
return buf;
}
int main(int argc, char *argv[]) {
int i;
void *ret;
int arr[N];
pthread_t pt[N];
for (i = 0; i < N; i++) {
arr[i] = i;
pthread_create(&pt[i], NULL, run, &arr[i]);
}
for (i = 0; i < N; i++) {
pthread_join(pt[i], &ret);
printf("Thread %d returned: %s\n", i, (char*)ret);
free(ret);
}
return EXIT_SUCCESS;
}
Note that you don't need to use pthread_join() calls. You can also cal pthread_exit() from the main thread so that only the main thread exit and other threads continue.
The Idea here is to create a file to be written to. I'm trying to create ten threads and have them print to the file 10 times each. Using a semaphore to stop multiple threads from writing to the file at once. Everything compiles and I don't get an error exit, however I can't understand why running the program numerous times: 1)It doesn't print 100 lines to the file, infact it's far less 2) The number of lines printed to the file vary each time.
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>
#define READ "r"
#define NEW "w"
#define ADD "a"
#define NL "\n"
#define TAB "\t"
#define FNAME "PROCTAB.txt"
#define MAX_STRING_LEN 80
#define NUMBER_OF_THREADS 10
FILE *fp;
sem_t mutex;
int counter;
FILE *makeTextFile(char *fname, char mode){
FILE *localFP;
localFP = fopen(fname, &mode);
return (localFP);
}
void *print_message(void *tid){
int i;
for (i = 0; i < 10; i++){
sem_wait(&mutex);
fp = fopen(FNAME, ADD);
fprintf(fp, "Thread %d is running.\n", tid);
fclose(fp);
sem_post(&mutex);
}
}
int threads(){
const char *fName = "PROCTAB.txt";
int status;
pthread_t threads[NUMBER_OF_THREADS];
fp = makeTextFile(FNAME, 'w');
fprintf(fp, "Process ID: %ld\n", (long)getpid());
fclose(fp);
int i;
for (i =0; i < NUMBER_OF_THREADS; i++){
status = pthread_create(&threads[i], NULL, &print_message, (void *)i);
if (status != 0){
printf("pthread_create returned error code %d\n", status);
exit(-1);
}
}
return 0;
}
My main function is contained in a separate file.
You need to wait for all thread to finish before you exit the program.
if you add trace you will see which thread is finish.
void *print_message(void *tid){
int i;
for (i = 0; i < 10; i++){
sem_wait(&mutex);
fp = fopen(FNAME, ADD);
fprintf(fp, "Thread %d is running.\n", tid);
fclose(fp);
sem_post(&mutex);
printf ( "Thread %d has finished.\n", tid);
}
}
This is how you wait for all threads to finish
/* Wait for Threads to Finish */
for (i=0; i<NUMTHREADS; i++) {
pthread_join(thread[i], NULL);
}