在堆中分配函数的返回值

时间:2018-06-12 11:50:48

标签: c malloc

我在程序的部分中分配函数的返回值时遇到问题。当我在main中尝试它时,它会出现错误“Segmentation fault”。我相信这是因为我的数组的大小,这是我之前提到的返回值,因为当我使我的max_size更小时,代码正常工作(我认为高达45000)。当我在main中调用函数时,它使用堆栈的内存,这比堆的内存小得多。因此,我尝试在堆中调用该函数并在那里进行赋值,但编译器发出错误

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

之后我做了一些研究,发现堆栈是8 MB内存,大约8000000字节。然后我估计我的数组大小使用素数定理(最多1000000,大约有200000个素数)和sizeof(int) = 4 bit值,因此它给出100000字节,远小于8 MB。因此,我有两个问题:

  

1。虽然我的数组大小不是太大,但为什么编译器会出现分段错误错误?

     

2. 我如何在堆中而不是main中进行分配以避免此问题?

这是我的代码:

#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 :(得分:1)

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之前不能轻易分配。{1}}数组。可以通过评估prime-counting function来完成,但这可能比您想要为此项目做的更多。

答案 1 :(得分:1)

在listPrimes中对unsigned intj, k使用max_size,它可以正常运行。以下是经过测试的代码:

// #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;
}