0

I am trying to make a program which names all prime numbers up to n. When I enter numbers > 2 Million, the program crashes. Can someone help me?

#include <stdio.h>
#include <math.h>

void sieve(unsigned long long int n, char primes[]);

int main()
{
  unsigned long long int i, n = 2000000; // find the primes up to 500000
  char v[n];
  sieve(n, v);
  for (i=0;i<n;i++)
    if (v[i] == 1)
      printf("%I64u\n",i); // this just prints out each value if it's Prime
}

void sieve(unsigned long long int n, char primes[])
{
  unsigned long long int i, j;
  for (i=0;i<n;i++)
    primes[i]=1; // we initialize the sieve list to all 1's (True)
  primes[0]=0,primes[1]=0; // Set the first two numbers (0 and 1) to 0 (False)
  for (i=2;i<sqrt(n);i++) // loop through all the numbers up to the sqrt(n)
    for (j=i*i;j<n;j+=i) // mark off each factor of i by setting it to 0 (False)
      primes[j] = 0;
}

Error message:

Process returned -1073741571 (0xC00000FD) execution time : 2.032 s

renno
  • 2,659
  • 2
  • 27
  • 58
Nord
  • 7
  • 2
  • Knowing the message with which it crashes might help. `char v[n];` for n=2M inside main may be an issue as that variable will be allocated from the stack, which in most cases is quite limited in size. – fvu Nov 29 '17 at 19:04
  • 1
    Using `i` as a counter for a loop *and* an nested loop? Sounds like a trouble. – Eugene Sh. Nov 29 '17 at 19:05
  • @fvu Process returned -1073741571 (0xC00000FD) execution time : 2.032 s – Nord Nov 29 '17 at 19:07
  • 1
    Use bit storage. That will give you 8x the range. – Weather Vane Nov 29 '17 at 19:08
  • @EugeneSh. No. The programm works perfectly for numbers up to 2000000. I need to use the same i in both loops – Nord Nov 29 '17 at 19:13
  • @EugeneSh. The indenting is off, but assuming the brackets are correct, the second for loop using `i` is not nested within the first for loop. The first for loop is purely for initialization of the `primes` array – Taelsin Nov 29 '17 at 19:16
  • @Taelsin Oh my. You are right. The indentation is not just terrible, it is highly misleading here. – Eugene Sh. Nov 29 '17 at 19:17
  • `char v[n]` puts two megabytes on the stack--that might be too much for your runtime. Use `malloc`. Even better, use malloc and bit-manipulation so that you only need one bit per number. – Lee Daniel Crocker Nov 29 '17 at 20:09

2 Answers2

1

Stick to the name of this website; you are experiencing a stack overflow. ;-)

Try

char *v = malloc(n);

and

void sieve(unsigned long long int n, char *primes)

respectively. Of course, you will also need

free(v);

Apart from that, I haven't checked your algorithm for correctness.

Pedro
  • 842
  • 6
  • 16
  • I never worked with pointers or the malloc function, but I tried to do this anyway. So now I have the following problem: at the line with "sieve(n, v);" neither "sieve(n, v);" nor "sieve(n, v*);" works. What should I do there? With v: "passing argument 2 of 'sieve' from incompatible pointer type" With *v: "'sieve' makes pointer from integer without a cast" – Nord Nov 29 '17 at 19:30
  • Pedram Azad, As OP is having trouble which may later include memory capacity issues, checking for `malloc()` success is prudent. – chux - Reinstate Monica Nov 29 '17 at 19:33
  • It should compile without any further changes. Maybe you forgot to adapt the declaration or the definition of your function sieve? You need to adapt both. – Pedro Nov 29 '17 at 19:33
  • 1
    @chux We are talking about less than 2 MB of memory. For heap allocation, this can only become problematic for really exotic systems. And I do not assume that the OP is doing DSP programming. But ok, for use with a lot larger n, a check would be useful. – Pedro Nov 29 '17 at 19:36
  • OP could be on an interactive system emulating a real computer and for student purposes works in a small sandbox - the initial issue is a memory one. IAC, learners do _interesting things_ and checking `malloc()` can discover an error faster. Yet if a goal is [code golf](https://codegolf.stackexchange.com), then yes, do not bother with a `malloc()` check. – chux - Reinstate Monica Nov 29 '17 at 20:00
1

The problem is because your program did not have enough memory reserved and as mentioned by @Pedram Azad you had an stack overflow. You can by-pass that by allocating more memory to your var (malloc).

Also, you need to start using brackets for your code blocks (loops and conditional statements). It helps to visualize problems. The indentation was very confusing.

#include <stdio.h>
#include <math.h>
#include <stdlib.h>

void sieve(unsigned long long int, char *);


int main()
{
  unsigned long long int i, n = 63000000; // find the primes up to 500000
  char *v = (char*) malloc(n*sizeof(char));
  sieve(n, v);
  for (i=0; i<n; i++) {
    if (v[i] == 1) {
      printf("%lld\n",i); // this just prints out each value if it's Prime
    }
  }
  free(v);
}

void sieve(unsigned long long int n, char *primes)
{
  unsigned long long int i, j;
  for (i=0; i<n; i++) {
    primes[i]=1; // we initialize the sieve list to all 1's (True)
  }
  // Set the first two numbers (0 and 1) to 0 (False)
  primes[0]=0;
  primes[1]=0;
  // loop through all the numbers up to the sqrt(n)
  for (i=2; i<sqrt(n); i++) {
    for (j=i*i; j<n; j+=i) {
      // mark off each factor of i by setting it to 0 (False)
      primes[j] = 0;
    }
  }
}
renno
  • 2,659
  • 2
  • 27
  • 58