因此,我正在制作下一个作业,输入数字将被解散,以便在输出中进行素数乘法。当它只显示素数2时我很困惑,所以我使用这个函数对分配的素数数组进行了适当的控制转储:
long* eratosthen(long max) {
bool grid[max + 1];
for(long i = 0; i < max + 1; ++i) {
grid[i] = true;
}
for(long i = 2; i < max + 1; ++i) {
if(grid[i]) {
for(long j = i * 2; j < max + 1; ++j) {
grid[j] = false;
}
}
}
long *primes;
primes = (long*)malloc((max + 1) * sizeof(long));
long index = 0;
for(long i = 2; i < max + 1; ++i) {
if(grid[i]) {
primes[index++] = i;
}
}
return primes;
}
由于某些未知原因,转储仅显示2
并结束。调用转储由以下代码组成:
int main(void) {
// Prime numbers get calculated first
long *primes;
primes = eratosthen(1000000);
// Control code
fprintf(stdout, "Control dump of primes array:\n");
for(long i = 0; i < sizeof(primes) / sizeof(long); ++i) {
fprintf(stdout, "%li\n", primes[i]);
}
int ret = 0;
/// ...
return ret;
}
//编辑:所以在你的所有答案之后,我会将我的问题更新为当前状态。主程序: int main(void){ //首先计算素数 长*素数; primes = eratosthen(1000000);
// Control code
fprintf(stdout, "Control dump of primes array:\n");
for( ; *primes != 0 ; primes++) {
fprintf(stdout, "%li\n", *primes);
}
int ret = 0;
}
生成素数函数:
long* eratosthen(long max) {
bool *grid;
grid = (bool*)malloc((max + 1) * sizeof(bool));
index = 0;
for(long i = 0; i < max + 1; ++i) {
*(grid + index) = true;
index++;
}
index = 2;
index_2 = 2;
for(long i = 2; i < max + 1; ++i) {
if(*(grid + index)) {
for(long j = i * 2; j < max + 1; j += i) {
*(grid + 2 * index_2) = false;
index_2++;
}
index++;
}
}
long *primes;
primes = (long *)malloc((max + 1) * sizeof(long));
index = 0;
for(long i = 0; i < max + 1; ++i) {
*(primes + index) = 0;
index++;
}
index = 0;
index_2 = 2;
for(long i = 2; i < max + 1; ++i) {
if(*(grid + index_2)) {
*(primes + index) = i;
index++;
index_2++;
}
}
// free the grid
free(grid);
return primes;
}
如前所述,Ubuntu终端显示以下行:
Neoprávněný přístup do paměti (SIGSEGV) (core dumped [obraz paměti uložen])
这样翻译:
Forbidden access to memory (SIGSEGV) (core dumped [memory image saved])
它是什么意思以及如何摆脱它? :(
答案 0 :(得分:3)
对代码的最简单修复可能是在素数数组的末尾添加一个0的sentinel值,并在main()
中重写检查条件。正如评论中广泛解释的那样,您当前的测试:
for(long i = 0; i < sizeof(primes) / sizeof(long); ++i) {
无可救药地错了。您不得尝试使用sizeof
,因为它根本无法执行您希望它执行的操作。
此代码有效:
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
static
long *eratosthen(long max)
{
bool grid[max + 1];
for (long i = 0; i < max + 1; ++i)
grid[i] = true;
for (long i = 2; i < max + 1; ++i)
{
if (grid[i])
{
for (long j = i * 2; j < max + 1; j += i) // Key fix
grid[j] = false;
}
}
long *primes;
primes = (long *)malloc((max + 1) * sizeof(long));
long index = 0;
for (long i = 2; i < max + 1; ++i)
{
if (grid[i])
primes[index++] = i;
}
primes[index] = 0; // Sentinel
return primes;
}
int main(void)
{
// Prime numbers get calculated first
long *primes = eratosthen(1000000);
fprintf(stdout, "Control dump of primes array:\n");
for (long i = 0; primes[i] != 0; ++i)
{
printf("%7li", primes[i]);
if (i % 10 == 9)
putchar('\n');
}
putchar('\n');
return 0;
}
我修改了代码,每行打印10个数字。我在main()
中更改了循环中的条件。我在函数中做了两个关键的改变 - 一个是正确计算素数的倍数,另一个是在素数列表的末尾添加哨兵。
它生成一个以
开头的78,498个素数列表 2 3 5 7 11 13 17 19 23 29
31 37 41 43 47 53 59 61 67 71
73 79 83 89 97 101 103 107 109 113
以:
结尾 999563 999599 999611 999613 999623 999631 999653 999667 999671 999683
999721 999727 999749 999763 999769 999773 999809 999853 999863 999883
999907 999917 999931 999953 999959 999961 999979 999983
您可能会注意到代码不会释放primes
- 它可以说是应该的。你可能会注意到为素数分配的空间大大超过了所需的空间(一百万而不是八万);您可以使用realloc()
缩小分配的空间,或者使用较不保守(或者我的意思是减少挥霍?)估计所需的条目数。