【发布时间】:2019-09-23 13:20:47
【问题描述】:
我已经实现了以下版本的埃拉托色尼筛法,它在堆上分配内存来存储表示素数的数组。
void sieve(int *primes, int n) {
for (int i = 0; i < n - 1; i++) {
primes[i] = 1;
}
for (int p = 2; p <= n; p++) {
if (primes[p - 2] == 1) {
for (int i = 2*p - 2; i < n; i += p) {
primes[i] = 0;
}
}
}
}
void print_sieves(int n) {
if (n < 3) return;
int *primes = (int*) malloc((n - 1) * sizeof(int));
sieve(primes, n);
int print_counter = 0;
for (int i = 0; i < n - 1; i++) {
if (primes[i] == 1) {
printf("%10d ", i + 2);
print_counter++;
if (print_counter % COLUMNS == 0)
printf("\n");
}
}
free(primes);
printf("\n");
}
对于传递给print_sieves 的大多数参数,程序按预期工作,但是,当将15 传递给print_sieves 时,我最终会出现以下错误:
a.out: malloc.c:2392: sysmalloc: Assertion `(old_top == initial_top (av) && old_size == 0) || ((unsigned long) (old_size) >= MINSIZE && prev_inuse (old_top) && ((unsigned long) old_end & (pagesize - 1)) == 0)' failed.
Aborted (core dumped)
对于这个程序的一个稍微不同的版本,我在堆栈上分配内存来存储表示素数的数组,我遇到了一个不同的错误。也就是说,当试图找到太大的素数时,例如当使用参数10000000 调用print_sieves 时,我遇到了错误Segmentation fault (core dumped)。 sieve 的实现对于两个版本的程序是相同的,但 print_sieves 有细微的差别。下面是我在堆栈上分配内存的print_sieves 函数的代码:
void print_sieves(int n) {
if (n < 3) return;
int primes[n - 1];
sieve(primes, n);
int print_counter = 0;
for (int i = 0; i < n - 1; i++) {
if (primes[i] == 1) {
printf("%10d ", i + 2);
print_counter++;
if (print_counter % COLUMNS == 0)
printf("\n");
}
}
printf("\n");
}
我的猜测是我没有正确管理内存,但我不知道我哪里出错了。什么可能导致这些错误以及如何解决?
【问题讨论】:
-
在这两种变体中,您都为 n - 1 个整数分配空间,同时循环到并包括 n。尝试为 n + 1 分配空间
-
@hager Allocating space for n + 1 ints 解决了第一个错误,即为基于堆的实现调用
print_sieves(15)时出现的错误,但第二个错误仍然存在。 -
为
nints分配空间也足以解决第一个问题。我想知道为什么为n - 1ints 分配空间是不够的,因为我在传递参数n时检查了闭区间[2, n]中的所有整数,其中只有n - 1。 -
这取决于您运行的平台,在我的 linux 桌面上,默认的最大堆栈大小为 8192 kB。您似乎有相同的限制,因为
2090000 * sizeof(int)那时几乎不适合堆栈。 -
这不是您的问题的原因,但是当我们在这里时,我建议您阅读并理解the question on why not to cast the return value of
malloc()and family in C。首选int *primes = malloc(sizeof *primes * (n+1));
标签: c memory-management sieve-of-eratosthenes