0
votes

I executed the below C program which prints a the primes below the given N (N < 4294967295). It went fine when executed in SunOS, but I'm getting Segmentation fault (core dumped) when running in Ubuntu(compiled it with gcc compilter). Can anyone please let me know where I went wrong. Mentioned below the compiler versions of SunOS and Ubuntu 12.10

cc -V

cc: Sun C 5.9 SunOS_sparc Patch 124867-01 2007/07/12

gcc -v

Using built-in specs. COLLECT_GCC=gcc COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.7/lto-wrapper Target: x86_64-linux-gnu Configured with: ../src/configure -v --with-pkgversion='Ubuntu/Linaro 4.7.2-2ubuntu1' --with-bugurl=file:///usr/share/doc/gcc-4.7/README.Bugs --enable-languages=c,c++,go,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.7 --enable-shared --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.7 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --enable-plugin --enable-objc-gc --disable-werror --with-arch-32=i686 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu Thread model: posix gcc version 4.7.2 (Ubuntu/Linaro 4.7.2-2ubuntu1)

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<inttypes.h>

int main()
{
FILE *fpin,*fpout;
char ch[11], file_name[100];
long long int num1=0,i,tmp=0;
long long int *arr;

printf("enter file name:: ");
gets(file_name);

fpin = fopen(file_name,"r");
fpout = fopen("/home/code/output.c","w");

while(1)
{
 fgets(ch,11,fpin);
 if (!feof(fpin))
 {
   num1=atoll(ch);

   arr = prime_number(num1);

   for(i=0;*(arr+i)!='\0';i++)
      {
         fprintf(fpout,"%llu",*(arr+i));
         if(*(arr+i+1) == '\0')
             fputc('.',fpout);
         else
             fputc(',',fpout);
      }

 }
 else 
 {
   fclose(fpin);
   fclose(fpout);
   break;
 }
}

}

prime_number(long long int n)
{
  long long int i,j,total=0,a[200];
  int count=0;

  printf("\n%llu \n",n);

  for (j=2;j<=n;j++)
  {
     count = 0;
     for (i=1;i<=j;i++)
       {`enter code here`
         if ((j%i) == 0)
           count++;

         if (count > 2)
            break;
        }
     if (count==2)
        {
          a[total] = j; 
          total++; 
        }
  } 
return(&a[0]);
}
2
In addition to returning the address of a local variable, a[200] is a bit small to store the primes in any nontrivial range. And your prime testing is woefully inefficient (though you break as soon as you found the third divisor, that's a good start). Divide only to the square root, the smallest prime divisor of a composite number cannot exceed the square root.Daniel Fischer
Hi @DanielFischer tried as you suggested and the execution time reduced by half. ThanksHitendra Valluri

2 Answers

2
votes

At the end of your prime_number funciton, you are returning a pointer to a variable which is defined in (the stack of) the prime_number function itself. Since when the function exists, the contents of its stack are effectivley vaporized, you are returning an invalid pointer.

Of course, depending on what system, OS, etc you are running, the contents of the stack may have not been immediatley overwritten and would APPEAR valid for a short period of time, but this is just luck.

Try either mallocing a return result (and freeing with your caller), or passing the array TO the prime_number function. This way, the contents will remain valid for the caller.

1
votes
return(&a[0]);

You're returning a pointer to a local variable, which doesn't exist after your function returns.

If you run gcc with warnings, your compiler should tell you this.