使用长数据类型时Malloc()失败
下面的代码打印出[m,n]之间的所有素数。 当我使用unsigned int时,malloc在我的64位系统上可以完美地工作到使用长数据类型时Malloc()失败,c,malloc,C,Malloc,下面的代码打印出[m,n]之间的所有素数。 当我使用unsigned int时,malloc在我的64位系统上可以完美地工作到10^9 #include <stdio.h> #include <string.h> #include <stdbool.h> #include <stdlib.h> #include <time.h> #define true 1 #define false 0 void
10^9
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <stdlib.h>
#include <time.h>
#define true 1
#define false 0
void SieveOfEratosthenes(unsigned int m ,unsigned int n) {
bool *prime;
prime = (bool*)malloc(m - n + 2);
if (!prime) {
printf("FAIL\n");
return;
}
memset(prime, true, (m - n + 2));
unsigned int i = 2;
for (i = 2; i * i <= n; i++) {
if (prime[i] == true) {
for (unsigned int j = i * 2; j <= n; j += i)
prime[j] = false;
}
}
for (i = m; i <= n; i++)
if (prime[i] && i != 1)
printf("%u \n", i);
}
int main() {
clock_t begin,end;
unsigned int m, n;
scanf("%u %u", &m, &n);
begin = clock();
SieveOfEratosthenes(m, n);
end = clock();
double time_spent = (double)(end - begin) / CLOCKS_PER_SEC;
printf("\nTime Taken : %lf secs\n", time_spent);
return 0;
}
由于以下原因,您的代码具有未定义的行为:
unsigned int m, n;
scanf("%llu %llu", &m, &n);
此外,您没有分配适当的内存量:
prime = (bool*)malloc(m - n + 2);
如果m
小于n+2
,则大小将变成一个巨大的数字。它只适用于unsigned int
,因为您可以在系统上分配4GB或16GB内存
事实上,给定您的算法,您必须分配n+1
元素,因为在筛选过程中,您使用从2开始的数字对该数组进行索引
此外,对于这个数组,您应该使用无符号字符
而不是bool
,因为类型bool
可以大于1字节
以下是修改后的版本:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
void SieveOfEratosthenes(unsigned long long m, unsigned long long n) {
unsigned char *prime = malloc(n + 1);
if (!prime) {
printf("FAIL\n");
return;
}
memset(prime, 1, n + 1);
unsigned long long i, j;
for (i = 2; i * i <= n; i++) {
if (prime[i]) {
for (j = i * 2; j <= n; j += i)
prime[j] = 0;
}
}
for (i = m; i <= n; i++) {
if (prime[i] && i != 1)
printf("%llu\n", i);
}
}
int main() {
clock_t begin, end;
unsigned long long int m, n;
if (scanf("%llu %llu", &m, &n) == 2) {
begin = clock();
SieveOfEratosthenes(m, n);
end = clock();
double time_spent = (double)(end - begin) / CLOCKS_PER_SEC;
printf("\nTime Taken : %f secs\n", time_spent);
}
return 0;
}
您的系统上的
大小是多少?(正如malloc
将size\u t
作为输入)(代码审查:为什么不将#包括?)malloc还需要像->malloc这样的大小(无论大小(数据类型))
。使用sizeof()
运算符相应地分配内存。请显示您提供的产生不希望的输出的输入。您的大小计算为m-n+2
,对于m==1
和n==100
为负值。您必须确保m>=n
。(但是你的循环i=m;i和OP应该从中得到警告。他正在使用malloc()-有大量未定义、未指定和实现定义的行为需要担心!这很尴尬,我意识到我是在做m-n+2
而不是n-m+2
。所以正如你所说,它是偶然为unsigned int
工作的。我不明白为什么OP没有添加像printf(“%llu%llu\n”,m,n)
在malloc()之前(
(如果没有IDE调试器)。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
void SieveOfEratosthenes(unsigned long long m, unsigned long long n) {
unsigned char *prime = malloc(n + 1);
if (!prime) {
printf("FAIL\n");
return;
}
memset(prime, 1, n + 1);
unsigned long long i, j;
for (i = 2; i * i <= n; i++) {
if (prime[i]) {
for (j = i * 2; j <= n; j += i)
prime[j] = 0;
}
}
for (i = m; i <= n; i++) {
if (prime[i] && i != 1)
printf("%llu\n", i);
}
}
int main() {
clock_t begin, end;
unsigned long long int m, n;
if (scanf("%llu %llu", &m, &n) == 2) {
begin = clock();
SieveOfEratosthenes(m, n);
end = clock();
double time_spent = (double)(end - begin) / CLOCKS_PER_SEC;
printf("\nTime Taken : %f secs\n", time_spent);
}
return 0;
}
void SieveOfEratosthenes(unsigned long long m, unsigned long long n) {
unsigned int maxp = (unsigned int)(ceil(sqrt(n)) + 1);
unsigned char *composite = calloc(maxp, 1);
unsigned char *slice = calloc(n - m + 1, 1);
if (!composite || !slice) {
free(composite);
free(slice);
printf("FAIL\n");
return;
}
/* compute the primes */
unsigned int p, q;
for (p = 2; p * p < maxp; p++) {
if (!composite[p]) {
for (q = p * 2; q < maxp; q += p)
composite[p] = 1;
}
}
/* sieve the slice */
unsigned long long i;
if (m == 0)
slice[0] = 1;
if (m <= 1 && n >= 1)
slice[1 - m] = 1;
for (p = 2; p < maxp; p++) {
if (!composite[p]) {
i = 2 * p;
if (i < m) {
i = m - m % p;
if (i < m)
i += p;
}
while (i <= n) {
slice[i - m] = 1;
i += p;
}
}
}
for (i = m; i <= n; i++) {
if (!slice[i - m])
printf("%llu\n", i);
}
free(composite);
free(slice);
}