0

I'm trying to make a program that takes a text from a file, and after that, it tells me if that text contains a string that I want tho search. The idea is that I must do everything with a process and multiple threads. The number of threads it's a variable number (I should tell from the terminal how many threads I want). If for example, I want 4 threads, the text from the file will be split into 4 strings, and every thread will work with their own string and will search in that string what word I want to find.

For verifying myself that everything works ok, I tried to print some variables on the screen (in server.c). And here I encountered a problem and I can't figure it out. Even if I told the program to print on the screen the "init" variable, it doesn't print anything. Size is printed, nr_thr is printed, everything it's ok until I reach the part when I say to print "init". And obvious, the entire program it's not working.

How can I fix it? It's ok the idea of the program?

This is server.c

###########Server.c##########
#include <unistd.h>
#include <sys/types.h>
#include <errno.h>
#include <stdio.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <pthread.h>

struct argum{
  char string[100];
  char cautat[100];
};


void *cautare(void *data){
  int rez;
  printf("AM ajuns in thread");
  struct argum *argum = data;
  int i,j,k;
  if (strstr(argum->string,argum->cautat)){
    printf("Exista in string");
    rez=1;
  }
  else{
    printf("Nu exista in string asa ceva");
    rez=0;
  }

  return (void*)rez;
}

int main(int argc, char**argv){
  struct argum *argum = malloc(sizeof(struct argum));
  char buffer[1000];
  int nr_thr;
  int df1;
  ssize_t in, out;
  int init=0;
  int i;
  char *a[100];
  char b[1000];

  nr_thr=atoi(argv[3]);
  printf("\n Nr threaduri:%d \n",nr_thr);
  df1 = open(argv[1], O_RDWR);

  if (df1 == -1){
      perror("eroare deschidere ");
      //exit(1);
  }

  int size=lseek(df1, 0, SEEK_END);
  printf("\nSize:%d\n",size);

  lseek(df1, 0, SEEK_SET);

  for(i=0; i<=size; i++){
    if((lseek(df1, i, SEEK_SET))==-1){
      perror("Eroare in fisier");
    }

    in=read(df1,&buffer[i],1);
  }

  printf("In fisier este textul:");
  puts(buffer);

  init = size/nr_thr;

  printf("\nInitial: %d ",init);

  int k=0;
  int l=0;
  int j;

  while(init<=size){
    for(i=init; i<=size/nr_thr; i++){
      b[k]=buffer[i];
      k++;
    }
      a[l]=b;
      init=size/nr_thr;
      if(nr_thr>0){
        nr_thr--;
        l++;
      }
      k=0;
    }


  int rezultat;

  int *return_vals = malloc(nr_thr * sizeof(int));

  pthread_t threads[10];

  for(i=0; i<nr_thr; ++i){
    puts(a[i]);
    argum->string[100]= *a[i];
    argum->cautat[100]= *argv[2];
    pthread_create(&threads[i],NULL,cautare,argum);
  }

  for(i=0; i<nr_thr; ++i){
    rezultat=pthread_join(threads[i],(void**) &return_vals[i]);
    }

  for(i = 0; i < nr_thr; i++)
  printf("Thread %d returned: %d\n", i, return_vals[i]);

  exit(1);
}

This is client.c, where I'm calling everything.

#include <unistd.h>
#include <sys/types.h>
#include <errno.h>
#include <stdio.h>
#include <sys/wait.h>
#include <stdlib.h>

int main(){
  int id,d, stare;
  int nr_thr;
  char nume_fis[100], nume_cuv[100];
  char thr[100];
  d=1;
  while(d==1){
    printf("> ");
    scanf("%s %s %d",nume_fis,nume_cuv,&nr_thr);

    sprintf(thr,"%d",nr_thr);
    id=fork();

    if(id<0){
      perror("Eroare la creare proces");
      return -1;
    }
    else if(id==0){ //fiu
      execl("./server","server",nume_fis,nume_cuv,thr,NULL);
      perror("eroare la exec");
    }
    else{
      wait(&stare);
      if(WIFEXITED(stare)){
        printf("%d",WEXITSTATUS(stare));
      }
    }

    printf("\nContinuati?(1 pt da)");
    scanf("%d",&d);
  }
  return 0;
}
Anko
  • 5,146
  • 4
  • 32
  • 42
  • On the `printf` issue, please see here: http://stackoverflow.com/q/1716296/694576 – alk Apr 11 '17 at 12:52
  • Yup, it worked with one of the suggestions from there. Now I found out that my threads are not starting to work at all. Any idea how to fix it? – Alexandru Bodea Apr 11 '17 at 13:03
  • 1
    Well, for a start, 'argum->string[100]' is out-of-bounds, hence UB :( – ThingyWotsit Apr 11 '17 at 13:07
  • Does the program work if not using threads at all? – alk Apr 11 '17 at 13:10
  • Yup, the program splits ok the text, everything it's where it needs to be. I think that the problem is at the structure and pointers, but dunno where. – Alexandru Bodea Apr 11 '17 at 13:24
  • @ThingyWotsit - What do you mean by out of bounds and with what should I replace it? – Alexandru Bodea Apr 11 '17 at 13:25
  • You are writing outside the limits of the array, valid indices are [0..99]. 'with what should I replace it?' - dunno - it's your code, you are in the best position to fix it. – ThingyWotsit Apr 11 '17 at 14:19
  • the basic premise of this application is undesirable. The reason it is undesirable is because the sub string being searched for may be split across more than one thread. – user3629249 Apr 12 '17 at 22:01
  • the posted 'server' code causes the compiler to output some 35 problems, of which about 1/2 are about the very first line in the posted code. – user3629249 Apr 12 '17 at 22:07
  • when calling any of the `scanf()` family of functions, 1) always check the returned value (not the parameter values) to assure the operation was successful. 2) when using the '%s' input/conversion specifier, always include a MAX CHARACTERS modifier that is one less than the length of the input buffer, so the user cannot overflow the buffer. Such overflow is undefined behavior and can/will lead to a seg fault event – user3629249 Apr 12 '17 at 22:17
  • This statement: `printf("> ");` does prompt the user, but fails to tell the user what the user is expected to enter. – user3629249 Apr 12 '17 at 22:19
  • the function: `fork()`, today, returns an `int` type that has been renamed to `pid_t` That is no guarantee that the next version of the compiler will return an `int` type. Suggest using the correct `pid_t`. – user3629249 Apr 12 '17 at 22:24
  • for ease of readability and understanding: 1) separate code blocks (for, if, else, while, do...while, switch, case, default) via a single blank line. 2) follow the axiom: *only one statement per line and (at most) one variable declaration per statement.* – user3629249 Apr 12 '17 at 22:27
  • the posted code contains some 'magic' numbers. 'magic' numbers are numbers with no basis. I.E. 100. 1000 'magic' numbers make the code much more difficult to understand, debug, maintain. Suggest giving those 'magic' numbers meaningful names via a `enum` statement or `#define` statements then using those meaningful names throughout the code. – user3629249 Apr 12 '17 at 22:30
  • when calling any of the heap allocation functions: (malloc, calloc, realloc), always check (!=NULL) the returned value to assure the operation was successful. – user3629249 Apr 12 '17 at 22:32
  • this line: `char *a[100];` is declaring 100 pointers to char, probably not what you want – user3629249 Apr 12 '17 at 22:34
  • never access `argv[]` beyond `argv[0]` without first checking `argc` to assure that the command line parameter actually exists – user3629249 Apr 12 '17 at 22:35
  • regarding this code block: ` if (df1 == -1) { perror("eroare deschidere "); //exit(1); }` since the call to `open()` failed, there is no file to pass to `lseek()` so the call to `exit()` should/must be executed, not commented out. Also, the return type from `lseek()` is a `off_t` not a `int`. Also, the returned value from `lseek()` should be checked (!= -1) to assure the operation was successful and a `off_t` is a `long int`, not a `int` – user3629249 Apr 12 '17 at 22:40
  • when outputting to stdout or stderr, always append a '\n' to the end of the format string so the buffer will immediately be flushed to the terminal. – user3629249 Apr 12 '17 at 22:47
  • the `read()` function does not NUL terminate the input, and `buffer[]` is not initialized to all '\0', so the immediate calling of `printf()` results in undefined behavior, which can lead to a seg fault event. Suggest, before the call to `printf()` insert: `buffer[in] = '\n';` – user3629249 Apr 12 '17 at 22:49
  • regarding this line: `init = size/nr_thr;` the variable `size` is from the returned value from `lseek()` (which could be `(long int)-1`) and there is a risk as this is an `integer` divide so if `nr_thr` is > `size` the result will be 0 – user3629249 Apr 12 '17 at 22:54
  • what happens when `size/nr_thr` is greater than 1000? Buffer overflow occurs, which is undefined behavior and can/will lead to a seg fault event – user3629249 Apr 12 '17 at 22:58
  • this line: `in=read(df1,&buffer[i],1);` always starts reading from the very first byte in the file. However, the code really wants to start reading from 'its' assigned byte (which may not be the first byte) – user3629249 Apr 12 '17 at 23:00
  • there is plenty more wrong with the posted code logic, but the above comments should get you thinking in the right direction. – user3629249 Apr 12 '17 at 23:05

0 Answers0