Friday 26 August 2016

c - Code doesn't enter in while loop even when condition is satisfied











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      /* basic I/O routines.   */
#include
#include /* define fork(), etc. */
#include /* define pid_t, etc. */
#include /* define wait(), etc. */
#include /* define signal(), etc. */
#include
#include
#include


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 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 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?


Answer



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).


No comments:

Post a Comment

c++ - Does curly brackets matter for empty constructor?

Those brackets declare an empty, inline constructor. In that case, with them, the constructor does exist, it merely does nothing more than t...