我在程序的堆部分分配函数的返回值时遇到问题。当我在main中尝试时,它给出了错误"分段错误"。我相信这是因为我的数组的大小,这是我之前提到的返回值,因为当我使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.如何使集合在堆而不是主中以避免此问题?
这是我的代码:
#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 = %dn", size);
for (int i = 0; i < size; i++) {
printf("%d th prime is %dn", i+1, primes[i]);
}
free(primes);
return 0;
}
在listPrimes中使用unsigned int
进行j, 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 = %dn", size);
for (int i = 0; i < size; i++)
{
printf ("%d th prime is %dn", i + 1, primes[i]);
}
free (primes);
return 0;
}
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
之前不容易分配。这可以通过评估素数计数函数来完成,但这可能比你想为这个项目做的要多。