0

Possible Duplicate:
“while( !feof( file ) )” is always wrong

I have a strange problem related to a while loop. I have a function which is called at the end of the parent of a process (print_file()) and it doesn't accept a true condition to go ahead. This is my simple multiprocess code as you can see below.

#include <stdio.h>     /* basic I/O routines.   */
#include <stdlib.h>
#include <unistd.h>    /* define fork(), etc.   */
#include <sys/types.h> /* define pid_t, etc.    */
#include <sys/wait.h>  /* define wait(), etc.   */
#include <signal.h>    /* define signal(), etc. */
#include <pthread.h>
#include <time.h>
#include <ctype.h>

void print_file(char* [], char* []);
void child_process(int,int);
void parent_process();
int counter=0;

int main(int argc, char* argv[]) {

    counter = atoi(argv[1]);
    int i,k;
    pid_t child_pid;
    int child_status;
    char* array[counter];
    srand ( time(NULL) );
    int temp;

    for(i=0; i<counter; i++){
        temp = rand()%4;
        child_pid = fork();

        switch(child_pid) {
            case -1:
                printf("Error occured with fork()\n");
                exit(1);
            case 0: 
                child_process(i,temp); /* Child Process */
                exit(0);
        }
    }

    wait(&child_status);
    parent_process();
    execl("/usr/bin/killall","killall","tail",(char *) 0);
    return 0;
}

void child_process(int i,int temp){

    FILE* fptr;
    fptr = fopen("sample.txt","a+");
    if( temp==0 ) {
        fprintf(fptr,"A %d\n",i);
    }
    else if( temp==1 ) {
        fprintf(fptr,"C %d\n",i);
    }
    else if( temp==2 ) {
        fprintf(fptr,"G %d\n",i);
    }
    else if( temp==3 ) {
        fprintf(fptr,"T %d\n",i);
    }
    fflush(fptr);
    sleep(1);
    fclose(fptr);
}

void parent_process(void){

    FILE* fptr;
    fptr = fopen("sample.txt","r");
    char* str = (char*)malloc(1);
    int temp,i,k;
    char* array_opst[counter];
    char* array[counter];

    i=0;
    while(!feof(fptr)){

        fscanf(fptr,"%s%d",str,&temp);
        if(feof(fptr))
            break;

        if(strcmp(str,"A")==0){
            array[temp]="A";
            array_opst[temp]="T";
            printf("Array[%d] = %s\n",temp,array[temp]);
        }
        else if(strcmp(str,"C")==0){
            array[temp]="C";
            array_opst[temp]="G";
            printf("Array[%d] = %s\n",temp,array[temp]);
        }
        else if(strcmp(str,"G")==0){
            array[temp]="G";
            array_opst[temp]="C";
            printf("Array[%d] = %s\n",temp,array[temp]);
        }
        else if(strcmp(str,"T")==0){
            array[temp]="T";
            array_opst[temp]="A";
            printf("Array[%d] = %s\n",temp,array[temp]);
        }
        i++;
    }
    fclose(fptr);
    free(str);
    print_file(array,array_opst);
}

void print_file(char* array[counter], char* array_opst[counter]) {

    int j=0,i=1;

    while(j<counter){
        printf("%d", i);
        i++;
        j++;
        if(i==10){
            i=0;
        }
    }
    return;
}

In the print_file function it never enters into the while loop even when the condition is satisfied. But whenever I put a printf on the first line of the print_file function to check if it does succesfully enter it prints. (Be carefull that counter is a global variable). What causes this problem?

Community
  • 1
  • 1
quartaela
  • 2,579
  • 16
  • 63
  • 99

1 Answers1

5

The output from the loop is not appearing due to stdout being buffered (the printf() statement inside the loop contains no \n and stdout is not explicitly fflush()d) and the call to execl() in main(), which replaces the current process image and stdout buffer is not flushed as usual on a normal program exit. Add a new-line character to the printf() or explicitly call fflush(stdout); after the loop.


There is a buffer overrun, causing undefined behaviour:

char* str = (char*)malloc(1);

allocates 1 byte, str is then used thus:

fscanf(fptr,"%s%d",str,&temp);

fscanf() adds a null terminator overruning the end of str even if only one char is read. I can't see a reason for dynamically allocating this or even when it needs to be an array as the format of the lines seems to be a single char followed by an int:

fprintf(fptr,"A %d\n",i);

To fix this problem, just use a char and the format specifier %c instead:

char ch;

if (2 == fscanf(fptr, "%c%d", &ch, &temp))
{
}

Always check return values (fopen(), fprintf(), fscanf() etc).

hmjd
  • 120,187
  • 20
  • 207
  • 252
  • i was facing with `segmentation fault error` before i used malloc thats why i allocate. on the other hand, why we check exactly `2` with the return value of fscanf _? – quartaela Oct 10 '12 at 21:33
  • 1
    @quartaela, `fscanf()` returns the number of assignments made. As the call of `fscanf()` is attempting to assign a value to `ch` and `temp` the return value will be 2 if successful. – hmjd Oct 10 '12 at 21:34
  • yeah i this way works too and more efficient i guess. on the other hand, it still couldnt enter in the while loop so that was not the reason of undefined behaviour _? – quartaela Oct 10 '12 at 21:42
  • @quartaela, did you change all code that used `str`? Like `strcmp()` for example? (Just checking). – hmjd Oct 10 '12 at 21:47
  • yeah i check characters like `if(str=='A')` – quartaela Oct 10 '12 at 21:48
  • @quartaela, are you 100% certain that the value read into `temp` results in `temp >= 0 && temp < counter` as `temp` is used as an index into arrays with `counter` number of elements. – hmjd Oct 10 '12 at 21:51
  • if we are talking about last function `void print_file(char* array[counter], char* array_opst[counter])` yeah i am absolutely sure and checked the `counter` value (which is global) and as you can see i assigned `j=0`. so it is impossible to fail the condition _? – quartaela Oct 10 '12 at 21:55
  • @quartaela, I am referring to `parent_process()` function. – hmjd Oct 10 '12 at 21:56
  • no i havent any problems about `parent_function()` the problem is in `print_file` function. and it never enters in the while loop. – quartaela Oct 10 '12 at 21:58
  • @quartaela, the `printf()` inside the loop may not be appearing due to `stdout` buffering. As you `execlp()` the `stdout` will not (I _think_) get flushed. Add a `\n` to `printf()` within the loop or `fflush(stdout);` after the loop. – hmjd Oct 10 '12 at 21:59
  • finally it worked!! i spent hours to realize this issue. thanks thanks thanksss :) – quartaela Oct 10 '12 at 22:02