【问题标题】:undefined behaviour on dynamic allocated arrays (segmentation fault)动态分配数组上的未定义行为(分段错误)
【发布时间】:2017-11-08 04:58:42
【问题描述】:

这个程序计算斐波那契数列的形式:t1, t2, t3 = t1 + t^2, t4 = t2+t3^2 ...

它需要三个输入 t1、t2 和您要计算的系列中的第 n 个数字。

由于数字呈指数增长,我使用数组来显示和对大数字执行操作。

问题:

我遇到了一些奇怪的错误:

bsquare[j] = *b[j]

使用输入 0 1 8 重新创建错误,它适用于最多 7 的输入。我也尝试使用 gdb 进行调试,但调试器显示当我使用 p **b@50 和 bn 时内存是可访问的有效。我错过了一些未定义的行为吗?

代码

#include<stdio.h>
#include<stdlib.h>

int carry = 0;
int fibo( int **a, int **b, int **c, int n);
void sum(int *a, int *b, int *c, int *an, int *bn, int *cn);
void sqr(int *b, int *bn);
int main()
{   

    int *a, *b, *c;
    int t1, t2, n, i, bn;

    scanf("%d%d%d",&t1, &t2,&n);

    a = (int * ) calloc(100, sizeof(int));
    b = (int * ) calloc(100, sizeof(int));
    c = (int * ) calloc(100, sizeof(int));
    a[0] = t1; b[0] = t2;

    bn = fibo(&a,&b,&c,n);

    printf("\nNumber is: ");
    for(i = bn-1; i>=0; i--)
    printf("%d",b[i]);

    free(a);free(b);free(c);
    return 0;
}
void sqr(int *b, int *bn)
{   int c[50] = {0};
    int i , j ,k = 0;
    int temp = 0;
    for(i = 0; i < *bn; i++)
    {    k = i;
        carry = 0;
        for(j = 0; j < *bn ;j++)
        {
            temp = c[k] + b[i] * b[j] + carry;
            if(temp>9)
            {
                carry = temp / 10;
                c[k] = temp % 10;

            }
            else
            {
                c[k] =  temp;
                carry = 0;
            }
            k++;
        }
        if(carry !=0)
        {c[k++] = carry;
        }

    }

    for(i = 0; i<k; i++)
    {   
        b[i] = c[i];

    }

    *bn = k;



}

void sum(int *a, int *b, int *c, int *an, int *bn, int *cn)
{

    int i=0 , j ,k = 0;
    int *temp1;
    int temp = 0;
    for(j=0; j<*cn; j++)
     c[j] = 0;
            *cn = 0;
     carry = 0;
    for(; i < *bn && i < *an; i++)
    {   
        temp = a[i] + b[i] + carry;

        if(temp>9)
        {
            c[k] = temp % 10;
            carry = temp/10;

        }
        else
        {
            c[k] = temp;
            carry = 0;
        }
        k++;
    }

    while(i<*an)
    {
        temp = carry + a[i];
        if(temp>9)
        {
            c[k] = temp % 10;
            carry = temp/10;

        }
        else
        {
            c[k] = temp;
            carry = 0;
        }
        k++;i++;
    }

    while(i<*bn)
    {
        temp = carry + b[i];
        if(temp>9)
        {
            c[k] = temp % 10;
            carry = temp/10;

        }
        else
        {
            c[k] = temp;
            carry = 0;
        }
        k++;i++;
    }
    if(carry!=0)
    {
        c[k++] = carry;
    }

    *cn = k;




}

int fibo( int **a, int **b, int **c, int n)
{
    int i, j,*tmpdb;

    int bn = 1, an = 1, cn = 0, bsn = 0, temp;
    int bsquare[100] = {0};

    for(i = 3; i<= n; i++)
        {   
            for(j = 0; j<bn; j++)
                bsquare[j] = *b[j];

            bsn = bn;

            sqr(bsquare,&bsn);
            sum(*a,bsquare,*c,&an,&bsn,&cn);

            tmpdb = *a;
            *a = *b;
            *b = *c;
            *c = tmpdb;

            temp = an;
            an = bn;
            bn = cn;
            cn = temp;



        }
    return bn;

}

【问题讨论】:

  • *b[j] --> (*b)[j]
  • @BLUEPIXY 我看不出两者之间的区别,您能否提供一些见解。还有一些关于指针实际工作方式的参考。我对这件事有很多疑问。
  • DEMO

标签: c dynamic segmentation-fault undefined heap-memory


【解决方案1】:

您没有像预期的那样更新b[] 值。您已经存储了b[0]=t2,之后它不会在其他任何地方更新。所以你的程序在b[1] 出现分段错误。所以我会说只需更新b[] 数组,你就可以开始了。并且请练习在你的代码中提供一点注释,这真的很难阅读。

【讨论】:

  • 在 fibo() 中的每次迭代后,b 都会与 c 交换
【解决方案2】:

正如 BLUEPIXY 在 cmets 中指出的那样,*b[j] 应更改为 (*b)[j],因为您已将 b 作为双指针传递给 fibo,b 存储来自主函数的指针变量的地址,而主函数又存储地址数组存在。

*b[j] 将被评估为 *(*(b+j)) 存储在 b 中的地址有效(来自 main 的指针变量 b 的地址),b+j 将您带到无效地址,访问它可能会导致段错误

您需要数组中的第 j 个元素,其地址存储在 b 中,正确的访问方式是 (*b)[j] 其中 (*b) 为您获取数组的基地址

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-10-03
    • 1970-01-01
    • 1970-01-01
    • 2014-04-28
    • 2013-09-04
    • 2015-03-02
    • 1970-01-01
    • 2012-11-06
    相关资源
    最近更新 更多