我的问题是这段代码大部分时间都运行良好,但是如果我输入某些 n 值(我发现一些是 1000 和 111),它会给我一个 SIGSEGV 错误(我认为这就是你所说的)。我发现在标记上调用 free 时会发生错误,所以我在程序上使用 n = 1000 运行 valgrind,但我不知道该怎么做,或者如何解决这个错误。我真的在寻找如何解决这个错误的答案,不一定是算法本身,但它应该是 Eratosthenes 筛子的实现。谢谢大家。
代码:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int *eSieve(int n)
{
/*first number of the array is the number of primes*/
int i = 0;
int *num = 0;
int *marks = 0;
int *primes = 0;
int k = 1;
int m = 0;
int j = 0;
int nPrimes = 0;
num = malloc(sizeof(int) * n);
marks = malloc(sizeof(int) * n);
for (i = 0;i < n;i++) {
num[i] = i + 1;
marks[i] = 0;
}
marks[0] = 2; /*mark 1 as special */
i = 1;
/*1 is prime, 2 is composit*/
while (k <= (int) sqrt(n)) {
if (marks[k] == 0) {
m = num[k];
for (i = 2; j < n; i++) {
j = (m * i) - 1;
marks[j] = 1;
}
j = 0;
}
k++;
}
/*Count the primes*/
for (i = 0;i < n;i++) {
if (marks[i] == 0) {
nPrimes++;
}
}
primes = malloc(sizeof(int) * (nPrimes + 1));
primes[0] = nPrimes;
j = 1;
for (i = 0;i < (n);i++) {
if (marks[i] == 0) {
primes[j] = num[i];
j++;
}
}
free(num);
free(marks);
return primes;
}
int main(int argc, char **argv)
{
int i = 0;
int n = 0;
int *primes = 0;
if (argc < 2) {
printf("Need a number argument");
} else if (atoi(argv[1]) == 1) {
printf("Enter Num > 1");
} else if (atoi(argv[1]) < 0) {
printf("Enter a positive value");
} else {
n = atoi(argv[1]);
}
primes = eSieve(n);
for (i = 0;i < primes[0];i++) {
printf("%d, ", primes[i+1]);
}
printf("\nNumber of Primes: %d\n", primes[0]);
return 0;
}
Valgrind 输出
==3970== Memcheck, a memory error detector
==3970== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.
==3970== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==3970== Command: ./sieve 1000
==3970==
==3970== Invalid write of size 4
==3970== at 0x400837: eSieve (sieve.c:34)
==3970== by 0x4009EF: main (sieve.c:76)
==3970== Address 0x5502fc4 is 4 bytes after a block of size 4,000 alloc'd
==3970== at 0x4C2C74C: malloc (vg_replace_malloc.c:270)
==3970== by 0x400777: eSieve (sieve.c:19)
==3970== by 0x4009EF: main (sieve.c:76)
==3970==
--3970-- VALGRIND INTERNAL ERROR: Valgrind received a signal 11 (SIGSEGV) - exiting
--3970-- si_code=1; Faulting address: 0x105502FE0; sp: 0x4030dad60
valgrind: the 'impossible' happened:
Killed by fatal signal
==3970== at 0x38061648: unlinkBlock (m_mallocfree.c:290)
==3970== by 0x380620C3: vgPlain_arena_malloc (m_mallocfree.c:1607)
==3970== by 0x38028474: vgMemCheck_new_block (mc_malloc_wrappers.c:263)
==3970== by 0x3802860A: vgMemCheck_malloc (mc_malloc_wrappers.c:301)
==3970== by 0x3809C800: vgPlain_scheduler (scheduler.c:1665)
==3970== by 0x380AB9EC: run_a_thread_NORETURN (syswrap-linux.c:103)
sched status:
running_tid=1
Thread 1: status = VgTs_Runnable
==3970== at 0x4C2C74C: malloc (vg_replace_malloc.c:270)
==3970== by 0x4008B1: eSieve (sieve.c:47)
==3970== by 0x4009EF: main (sieve.c:76)
Note: see also the FAQ in the source distribution.
It contains workarounds to several common problems.
In particular, if Valgrind aborted or crashed after
identifying problems in your program, there's a good chance
that fixing those problems will prevent Valgrind aborting or
crashing, especially if it happened in m_mallocfree.c.
If that doesn't help, please report this bug to: www.valgrind.org
In the bug report, send all the above text, the valgrind
version, and what OS and version you are using. Thanks.
错误信息:
sieve: malloc.c:2369: sysmalloc: Assertion `(old_top == (((mbinptr) (((char *) &((av)->bins[((1) - 1) * 2])) - __builtin_offsetof (struct malloc_chunk, fd)))) && old_size == 0) || ((unsigned long) (old_size) >= (unsigned long)((((__builtin_offsetof (struct malloc_chunk, fd_nextsize))+((2 * (sizeof(size_t))) - 1)) & ~((2 * (sizeof(size_t))) - 1))) && ((old_top)->size & 0x1) && ((unsigned long)old_end & pagemask) == 0)' failed.