Pergunta

So here's the code for primes sieve, and it gives correct output, does exactly what I want it to do, except ugly errors after printing correct result.

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

void prime_gen(int *, int);
void show_primes(unsigned long, unsigned long, int *, int);

int main(void)
{
  int no_testcases=0;
  int count=0;
  unsigned long lower=0,upper=0;
  unsigned long size;

  size=sqrt(1000000000);
  printf("%lu\n", size);
  int * primes, *primes_temp;;
  primes=(int *)calloc(size+1,sizeof(int));
  assert (primes!=NULL);

  prime_gen(primes, size+1); /* generates array of 0 and 1's indicating if index is a prime number */

  scanf("%d", &no_testcases); /* no of test cases */
  while (count<no_testcases)
  {
    scanf("%lu %lu", &lower, &upper);
    show_primes(lower, upper, primes, size+1); /* shows all prime numbers in given range */
    count++;
    if (count!=no_testcases)
      putchar('\n');
  }

  free(primes);

  return 0;
}

And the output:

31622
size=31623, set_index=63248, index=31625
1
1
10  
2
3
5
7
No of primes = 4
*** glibc detected *** ./a.out: double free or corruption (out): 0x09d49008 ***
a.out: malloc.c:2451: sYSMALLOc: Assertion `(old_top == (((mbinptr) (((char *) &((av)->bins[((1) - 1) * 2])) - __builtin_offsetof (struct malloc_chunk, fd)))) && old_size == 0) || ((unsigned long) (old_size) >= (unsigned long)((((__builtin_offsetof (struct malloc_chunk, fd_nextsize))+((2 * (sizeof(size_t))) - 1)) & ~((2 * (sizeof(size_t))) - 1))) && ((old_top)->size & 0x1) && ((unsigned long)old_end & pagemask) == 0)' failed.
Przerwane (core dumped)

Here's code for primes generator and show_primes:

void prime_gen(int * tab, int size) /* 0== is prime, 1== is not prime */
{
  tab[0]=1;
  tab[1]=1;
  unsigned long index=2;
  unsigned long set_index;


  for(index=2;index<=size;index++)
  {
    while (index<=size && tab[index]!=0) /* goes to next prime number */
    {
      index++;
    }
    for(set_index=index+index;set_index<=size;set_index+=index)
      tab[set_index]=1;
  }
  printf("size=%d, set_index=%lu, index=%lu\n", size, set_index, index);
}

void show_primes(unsigned long l, unsigned long u, int * array, int size)
{
  int index = 0;
  int is_prime=1;
  int primes_count=0;

  for(l;l<=u;l++)
  {
    if (l<=size) /* if l is valid index of array with primes */
    {
      if(array[l]==0)
      {
    printf("%lu\n", l);
    primes_count++;

      }
    }
    else /* if checked number is bigger than last index of array */
    {
      is_prime=1;
      for (index=2;index<=size;index++)
      {
    if (array[index]==0)
    {
      if (l%index==0)
      {
        is_prime=0;
        break;
      }
    }
      }
      if (is_prime)
      {
    printf("%lu\n", l);
    primes_count++;

      }
    }

  }
  printf("No of primes = %d\n", primes_count);
}

I narrowed it to free(primes) as the problem, because when removed error disappears and program terminated as supposed to. And I know array would be better here, but dynamic arrays are new to me and it's supposed to be my lesson on them. Many thanks for answers.

Foi útil?

Solução

My guess:

void prime_gen(int *, int);
void show_primes(unsigned long, unsigned long, int *, int);

int main(void)
{
  int no_testcases=0;
  int count=0;
  unsigned long lower=0,upper=0;
  unsigned long size;

  size=sqrt(1000000000);
  printf("%lu\n", size);
  int * primes, *primes_temp; *primes_head;
  primes=(int *)calloc(size+1,sizeof(int));
  primes_head = primes;
  assert (primes!=NULL);

  /* NOTE CHANGE BELOW */
  prime_gen(primes, size); /* generates array of 0 and 1's indicating if index is a prime number */

  scanf("%d", &no_testcases); /* no of test cases */
  while (count<no_testcases)
  {
    scanf("%lu %lu", &lower, &upper);
    /* NOTE CHANGE HERE */
    show_primes(lower, upper, primes, size); /* shows all prime numbers in given range */
    count++;
    if (count!=no_testcases)
      putchar('\n');
  }

  free(primes_head);

  return 0;
}

Outras dicas

In prime_gen function, you have this:

for(set_index=index+index;set_index<=size;set_index+=index)
  tab[set_index]=1;

You are overflowing your array. On the last iteration you write to element tab[set_index] with set_index value greater than size.

Try to change your for loop stop condition to: set_index < size

You are calling primes_gen and show_primes with the primes array and the size of the array. Inside those functions, you are reading from and writing to one past the bounds of the array:

for(set_index=index+index;set_index<=size;set_index+=index)
  tab[set_index] = 1;

This is corrupting your array and so your call to free() is failing.

try moving scanf("%lu %lu", &lower, &upper); outside of the loop

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top