Derrick Cheung
Derrick Cheung

Reputation: 1

mysterious segmentation fault in C

I am new to C, and came across a problem that I don't know how to solve. Could you have a look at buffer[fileSize] in unwhiten()? The problem that I'm having is that if I run this code, I will get a segmentation fault, but if I replace fileSize with any integer, the problem goes away. However, I defined fileSize as int, and I print it out, which also gives me an integer, so I really don't understand what happened or why it happened. Thank you!

#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#define BUFFER_SIZE 1000000
#include <string.h>
#include "whiten.h"


int main (int agrc, char *agrv[])
{
  whiten ();
  unwhiten ();

  return 0 ;
}


void unwhiten ()
 {
     FILE *input =fopen("2.txt","rb") , *output =  fopen("3.txt","ab") ;
     int patternLength =2 ,entryNum=0,counter=0 ,readNum,numProcessed=0 ,index ,fileSize;
     fseek(input,0L,SEEK_END);
     fileSize=ftell(input);
     fseek(input,0L,SEEK_SET);
     char buffer[fileSize] ,pattern[patternLength] ,*ft ;
     struct Entry table[ (int)exp2(patternLength)]  ;
     readNum=fread(buffer,sizeof(buffer[0]),sizeof (buffer),input);
     char recoveredBits[readNum];
     for (counter;counter<patternLength;counter++)  // output the first t bits and record the first pattern
     {
         if (buffer[counter]=='1')
         {
             fputc('1',output);
             recoveredBits[counter]='1';
         }
         else
         {
             fputc('0',output);
             recoveredBits[counter]='0';
         }

            pattern[counter]=buffer[counter];
     }
     numProcessed=patternLength;
       while (numProcessed<readNum)
     {
          index=searchTable(table,entryNum,pattern) ;

         if ( index==-1) // the table doesnt contain the entry
         {
              ft=malloc (sizeof (char)*(int)exp2(patternLength));
              strcpy(ft,pattern);
              table[entryNum].key=ft;
              table[entryNum].numOf0=0;
              table[entryNum].numOf1=0;
              index = entryNum++;
          }
               if (table[index].numOf0>=table[index].numOf1)//  they are equally likely
              {
                  if (buffer[numProcessed]=='0')  // prediction is made ,and it is right
                  {
                      fputc('0',output);
                      table[index].numOf0++;
                      recoveredBits[numProcessed]='0';
                  }
                  else
                  {
                       fputc('1',output); // prediction is wrong
                       table[index].numOf1++;
                       recoveredBits[numProcessed]='1';
                  }
              }
              else
              {
                  if (buffer[numProcessed]=='1')  // prediction is made ,and it is right
                  {
                       fputc('0',output);
                      table[index].numOf0++;
                      recoveredBits[numProcessed]='0';
                  }
                  else
                  {
                      fputc('1',output); // prediction is wrong
                      table[index].numOf1++;
                      recoveredBits[numProcessed]='1';
                  }
              }
           for (counter=1;counter<patternLength;counter++)  // shuffle the array
         {
             pattern[counter-1]=pattern[counter];
         }
         pattern[patternLength-1]=recoveredBits[numProcessed++];
       }
     fclose(input);
     fclose(output);

     for (counter=0;counter<entryNum;counter++)
     {
         free(table[counter].key);
     }

 }




 void whiten ()
 {
     FILE *input =fopen("1.txt","rb") , *output =  fopen("2.txt","ab") ;
     int patternLength =2 ,entryNum=0,counter=0 ,readNum,numProcessed=0 ,index;
     char buffer[BUFFER_SIZE] ,pattern[patternLength] ,*ft ;
     struct Entry table[ (int)exp2(patternLength)]  ;
     readNum=fread(buffer,sizeof(buffer[0]),sizeof (buffer),input);
     for (counter;counter<patternLength;counter++)  // output the first t bits and record the first pattern
     {
         if (buffer[counter]=='1')
             fputc('1',output);
         else
            fputc('0',output);
            pattern[counter]=buffer[counter];
     }
     numProcessed=patternLength;
       while (numProcessed<readNum)
     {
          index=searchTable(table,entryNum,pattern) ;

         if ( index==-1) // the table doesnt contain the entry
         {
              ft=malloc (sizeof (char)*(int)exp2(patternLength));
              strcpy(ft,pattern);
              table[entryNum].key=ft;
              table[entryNum].numOf0=0;
              table[entryNum].numOf1=0;
              index = entryNum++;
          }
               if (table[index].numOf0>=table[index].numOf1)//  they are equally likely
              {
                  if (buffer[numProcessed]=='0')  // prediction is made ,and it is right
                  {
                      fputc('0',output);
                      table[index].numOf0++;
                  }
                  else
                  {
                       fputc('1',output); // prediction is wrong
                       table[index].numOf1++;
                  }
              }
              else
              {
                  if (buffer[numProcessed]=='1')  // prediction is made ,and it is right
                  {
                      fputc('0',output);
                      table[index].numOf1++;
                  }
                  else
                  {
                      fputc('1',output); // prediction is wrong
                      table[index].numOf0++;
                  }
              }
           for (counter=1;counter<patternLength;counter++)  // shuffle the array
         {
             pattern[counter-1]=pattern[counter];
         }
         pattern[patternLength-1]=buffer[numProcessed++];
       }
     fclose(input);
     fclose(output);

     for (counter=0;counter<entryNum;counter++)
     {
         free(table[counter].key);
     }

 }

int searchTable ( struct Entry table[],int entryNum,char pattern[])
{
    int i=0;
    for (i;i<entryNum;i++)
    {
        if (strcmp(table[i].key,pattern)==0)
            return i;
    }

    return -1;
}

Upvotes: 0

Views: 85

Answers (1)

M.M
M.M

Reputation: 141534

strcpy(ft,pattern); is a problem. The strcpy function expects a null-terminated string, howeover pattern is not that. The strcpy will read past the end of pattern, causing undefined behaviour. You probably want to put a null terminator on (and increase the allocations of ft and pattern by one). It'd make sense to use sizeof pattern in your malloc rather than re-computing the size.

I'd also advise changing exp2(patternLength) to 1ul << patternLength, that avoids any possibility of rounding errors (exp2 is a floating point function).

Finally it'd be good to do some sanity checking on any values you use to size a VLA, e.g. char recoveredBits[readNum];. If readNum was negative, or less than patternLength, or something else you didn't expect, then you just get silent undefined behaviour which is hard to track down the source of.

Upvotes: 1

Related Questions