Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/amazon-s3/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C中的分段错误,可能在中/大型动态分配数组上_C_Segmentation Fault - Fatal编程技术网

C中的分段错误,可能在中/大型动态分配数组上

C中的分段错误,可能在中/大型动态分配数组上,c,segmentation-fault,C,Segmentation Fault,注意:我已经查看了其他分段错误公告,与我的问题密切相关的是在堆栈上创建大型数组最终导致溢出。但是,正如您从下面的代码中看到的,我在堆上进行分配,仍然遇到这个问题 我已经使用Valgrind和gdb对此进行了调试,他们告诉我:下面的函数代码中出现了“大小为4…NumberVisors的无效读取”或分段错误。奇怪的是,这适用于49141之前的所有数字,当它循环通过感兴趣的数字时,它将抛出错误或segfault这仅当它处于循环中时。当我输入一个没有循环的大数时,它将报告除数的数量,而不会出错或分段。有

注意:我已经查看了其他分段错误公告,与我的问题密切相关的是在堆栈上创建大型数组最终导致溢出。但是,正如您从下面的代码中看到的,我在堆上进行分配,仍然遇到这个问题

我已经使用Valgrind和gdb对此进行了调试,他们告诉我:下面的函数代码中出现了“大小为4…NumberVisors的无效读取”或分段错误。奇怪的是,这适用于49141之前的所有数字,当它循环通过感兴趣的数字时,它将抛出错误或segfault这仅当它处于循环中时。当我输入一个没有循环的大数时,它将报告除数的数量,而不会出错或分段。有人能看到下面代码中的问题吗?谢谢

int numberDivisors(int n) {
    int lim = (int)floor(sqrt((double)n));
    int *primes = (int*)calloc(n, sizeof(int));
    int *divisors = (int*)calloc(n, sizeof(int));
    int i, j, ctr;
    ctr = 0;

    if(primes && divisors) {
        for(i = 0; i < n; i++) {
            primes[i] = 1;
            divisors[i] = 0;
        }

        for(i = 2; i < lim; i++) {
            if(primes[i]) {
                for(j = i; i * j < n; j++) {
                    primes[i * j] = 0;
                }
            }
        }

        for(i = 2; i < n; i++) {
            if(primes[i]) {
                if(n % i == 0) divisors[i] = 1;
                for(j = i; i * j < n; j++) {
                    // int result = n % (i * j);
                    assert(i * j < n); //Added at lsk's request.  i * j passes the test.

                    //if(result == 0) {
                    if(n % (i * j) == 0) {
                        if(!divisors[i * j]) {
                            divisors[i * j] = 1;
                        }
                    }
                }
            }
        }

        for(i = 2; i < n; i++) {
            if(divisors[i]) ctr++;
        }

        ctr += 2;
    } else {
        printf("Allocation failed.");
    }
    free(primes);
    free(divisors);
    return ctr;
}
int数字查看器(int n){
内部直线=(内部)楼层(sqrt((双)n));
int*素数=(int*)calloc(n,sizeof(int));
int*除数=(int*)calloc(n,sizeof(int));
int i,j,ctr;
ctr=0;
if(素数和除数){
对于(i=0;i

UPDATE我将函数中的所有int都改为unsigned long(只是为了看看它是否可以工作),它现在运行得很好。但是,Umer是对的-我必须重新考虑算法,因为它需要的时间比需要的时间长,但这是另一个问题。感谢社区的帮助!

错误事实上是

if(!divisors[i * j]) {
   divisors[i * j] = 1;
}

由于整数溢出。请考虑一个简单的例子:

int n = 123123123;
int i = 57641;
int j = 74495;

printf("i         = %d\n", i);
printf("j         = %d\n", j);
printf("i * j     = %d\n", i*j);
printf("i*1.0 * j = %f\n", i*1.0 * j);
printf("n         = %d\n", n);
将生成以下输出:

i         = 57641
j         = 74495
i * j     = -1001001
i*1.0 * j = 4293966295.000000
n         = 123123123

如您所见,
i*j
是真的,但
i*j
是一个负整数。使用负索引索引
除数会导致崩溃。

错误实际上是

if(!divisors[i * j]) {
   divisors[i * j] = 1;
}

由于整数溢出。请考虑一个简单的例子:

int n = 123123123;
int i = 57641;
int j = 74495;

printf("i         = %d\n", i);
printf("j         = %d\n", j);
printf("i * j     = %d\n", i*j);
printf("i*1.0 * j = %f\n", i*1.0 * j);
printf("n         = %d\n", n);
将生成以下输出:

i         = 57641
j         = 74495
i * j     = -1001001
i*1.0 * j = 4293966295.000000
n         = 123123123

正如您所见,
i*j
是真的,但是
i*j
是一个负整数。使用负索引索引
除数会导致崩溃。

哪一行出现问题?我看到的唯一可疑代码是i*j被用作索引,它可能大于分配的大小。您可以添加assert()吗要检查这些条件吗?请添加到您的代码中。每次他使用ij时,它都在一个循环块中,条件ijfor
循环中的条件更改为
j
可避免算术溢出(除以
i
而不是
j
会给优化器留下优化空间。只要除以一个正整数,整数除法就不会溢出。哪一行是问题所在?我看到的唯一可疑代码是i*j被用作索引,它可能大于分配的大小。能否添加assert()要检查这些条件吗?请添加到您的代码中。每次他使用ij时,它都在一个循环块中,条件ijfor
循环中的条件更改为
j
可避免算术溢出(除以
i
而不是
j
会给优化器留下优化的空间。只要除以正整数,整数除法就不会溢出。我完全同意这就是问题所在。在我测试50059的
gdb
会话中,我得到:
(gdb)p除数
$1=(int*)0x100034000
(因此
除数可以),然后
(gdb)pi
和$2=47653`(可以),以及
(gdb)pj
$3=90129
(绝对不可以)我完全同意这就是问题所在。在我测试50059的
gdb
会话中,我得到了:
(gdb)p除数
$1=(int*)0x100034000
(因此
除数
是可以的),然后
(gdb)p i
和$2=47653`(这可能很好),以及
(gdb)p j
$3=90129
(这绝对不好)。在不同的机器上,在不同的
n
值下,我得到了不同的碰撞结果。