Присвоение возвращаемого значения функции в куче - PullRequest
0 голосов
/ 12 июня 2018

У меня проблемы с назначением возвращаемого значения функции в heap части программы.Когда я пробовал в основном, выдает ошибку «Ошибка сегментации» .Я полагаю, что это из-за размера моего массива, который является возвращаемым значением, о котором я упоминал ранее, потому что, когда я делаю max_size меньше, код работает правильно (я думаю, до 45000).Когда я вызываю функцию в main, она использует память стека, которая намного меньше памяти кучи.Поэтому я попытался вызвать функцию в куче и выполнить там назначение, но компилятор выдал ошибку

deneme.c:6:15: error: initializer element is not constant
 int *primes = listPrimes(1000000, &size);

После этого я провел некоторое исследование и обнаружил, что стек составляет 8 МБ памяти, что составляет около 8000000байт.Затем я оценил размер моего массива как теорему о простых числах (до 1000000, приблизительно 200000 простых чисел) и значение sizeof(int) = 4 bit, поэтому оно дает 100000 байтов, что намного меньше 8 МБ.Поэтому я имею в виду два вопроса:

1. Почему компилятор выдает ошибку ошибки сегментации, хотя размер моего массива не слишком велик?

2. Как я могу сделать назначение в куче вместо основного, чтобы избежать этой проблемы?

Вот мой код:

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

int *listPrimes(int max_size, int *size) {
        *size = 1;
        int *result = malloc(*size * sizeof(int));
        int i;
        int index = 1;
        // Finding the list of primes using a sieve algorithm:
        int *nums = malloc(max_size*sizeof(int));
        for (i = 0; i < max_size; i++) {
                nums[i] = i;
        }
        result[0] = 2;
        int j = 2;
        while (j < max_size) {
                int k = j;
                while (j*k <= max_size) {
                        nums[j*k] = 0;
                        k++;
                }
                if (j == 2) {
                        j++;
                        *size = *size + 1;
                        result = realloc(result, *size * sizeof(int));
                        result[index++] = nums[j];
                }
                else {
                        j += 2;
                        if (nums[j] != 0) {
                                *size = *size + 1;
                                result = realloc(result, *size * sizeof(int));
                                result[index++] = nums[j];
                        }
                }
        }
        return result;
}

и основная функция:

#include <stdio.h>
#include <stdlib.h>
#include "mathlib.h"

int size = 0;
int *primes = listPrimes(1000000, &size);

int main() {
        printf("size = %d\n", size);
        for (int i = 0; i < size; i++) {
                printf("%d th prime is %d\n", i+1, primes[i]);
        }
        free(primes);
        return 0;
}

Ответы [ 2 ]

0 голосов
/ 12 июня 2018

Используйте unsigned int для j, k и max_size в listPrimes, и все работает правильно.Ниже тестируемый код:

// #include "mathlib.h"
#include <math.h>
#include <stdlib.h>
#include <stdio.h>

int size = 0;

int *
listPrimes (unsigned int max_size, int *size)
{
  *size = 1;
  int *result = malloc (*size * sizeof (int));
  int i;
  int index = 1;
  // Finding the list of primes using a sieve algorithm:
  int *nums = malloc (max_size * sizeof (int));
  for (i = 0; i < max_size; i++)
    {
      nums[i] = i;
    }
  result[0] = 2;
  unsigned int j = 2;
  while (j < max_size)
    {
      unsigned int k = j;
      while (j * k <max_size)
    {
      nums[j * k] = 0;
      k++;
    }
      if (j == 2)
    {
      j++;
      *size = *size + 1;
      result = realloc (result, *size * sizeof (int));
      result[index++] = nums[j];
    }
      else
    {
      j += 2;
      if (nums[j] != 0)
        {
          *size = *size + 1;
          result = realloc (result, *size * sizeof (int));
          result[index++] = nums[j];
        }
    }
    }
   free(nums);
   return result;
}

int
main ()
{
  int *primes = listPrimes (1000000, &size);
  printf ("size = %d\n", size);
  for (int i = 0; i < size; i++)
    {
      printf ("%d th prime is %d\n", i + 1, primes[i]);
    }
  free (primes);
  return 0;
}
0 голосов
/ 12 июня 2018

nums выделено для max_size элементов, поэтому индекс его последнего элемента равен max-size-1.

. Этот цикл:

while (j*k <= max_size) {
     nums[j*k] = 0;
     k++;
}

может получить доступ к элементу синдекс j*k, равный max_size, что означает запись за конец массива.Цикл должен быть ограничен j*k < max_size.

Что касается вашего второго вопроса, размер массива result определяется при поиске простых чисел и не может быть легко вычислен заранее, поэтому его нельзя легко выделить дона звонок listPrimes.Это можно сделать, оценив функцию подсчета простых чисел , но это, вероятно, больше, чем вы хотите сделать для этого проекта.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...