2012-03-10 60 views
-2

我寫了一個代碼,它使用我自己的任意精度函數來計算斐波那契數,用於乘法和加法。代碼中的不可預知的SIGSEGV(運行時錯誤)

#include<iostream> 
#include<cstdio> 
#include<map> 
#include<cstring> 

using namespace std; 

#define max 3000 

struct data_type{ 
    int string[max]; 
}; 

struct data_type mul(struct data_type a,struct data_type b) { 
    struct data_type c; 
    memset(c.string,0,sizeof(int)*max); 
    int k; 
    int i,j; 
    for(i=max-1;i>0;i--) { 
     int num=a.string[i]; 
     int carry=0; 
     int rem=0; 
     k=i; 

     for(j=max-1;j>0;j--) { 
     int n=b.string[j]*num + carry; 
     int r=n%10; 
     carry=n/10; 
     int p=(c.string[k]+r+rem)%10; 
     rem=(c.string[k]+r+rem)/10; 
     c.string[k]=p; 
     k--; 
     } 
    } 

    return c; 
} 

struct data_type add(struct data_type a,struct data_type b) { 
    struct data_type c; 
    memset(c.string,0,sizeof(int)*max); 
    int carry=0; 
    int i,j; 
    int k=max-1; 

    for(i=max-1,j=max-1;i>0 && j>0;i--,j--) { 
     int res=(a.string[i] + b.string[j])+carry; 
     carry=res/10; 
     c.string[k--]=res%10; 
    } 

    return c; 
} 

void multiply(struct data_type f[2][2],struct data_type m[2][2]){ 

    struct data_type x,y,z,t; 
    x=add(mul(f[0][0],m[0][0]),mul(f[0][1],m[1][0]));  
    y=add(mul(f[0][0],m[0][1]),mul(f[0][1],m[1][1]));  
    z=add(mul(f[1][0],m[0][0]),mul(f[1][1],m[1][0]));  
    t=add(mul(f[1][0],m[0][1]),mul(f[1][1],m[1][1]));  

    f[0][0]=x; 
    f[0][1]=y; 
    f[1][0]=z; 
    f[1][1]=t;  
} 

void power(struct data_type f[2][2],unsigned long long n){ 

    if((n==0)||(n==1)) 
     return ; 
    struct data_type a,b; 
    memset(a.string,0,sizeof(int)*max); 
    memset(b.string,0,sizeof(int)*max); 
    a.string[max-1]=1; 
    b.string[max-1]=0; 
    struct data_type m[2][2]={{a,a},{a,b}}; 

    power(f,n/2); 

    multiply(f,f); 

    if(n%2 != 0) 
     multiply(f,m); 
    } 

    struct data_type fib(unsigned long long n){ 
    struct data_type a,b; 
    memset(a.string,0,sizeof(int)*max); 
    memset(b.string,0,sizeof(int)*max); 
    a.string[max-1]=1; 
    b.string[max-1]=0; 

    struct data_type f[2][2]={{a,a},{a,b}}; 

    if(n==0) 
     return b; 

    power(f,n-1); 
    return f[0][0]; 
} 

int main() 
{ 
    int t; 
    cin>>t; 

    for(int w=0;w<t;w++){ 
     unsigned long long n; 
     cin>>n; 
     struct data_type a,b,c; 

     a=fib(n-1); 
     b=fib(n+2); 
     c=add(a,b); 

     int ck=0; 

     for(int i=0;i<max;i++) { 
     if(c.string[i] && !ck) 
      ck=1; 

     if(ck) 
      cout<<c.string[i]; 
     } 

     cout<<"\n"; 
    } 

    return 0; 
} 

我的問題是,它顯示SIGSEGV上運行,但有時可以正常運行,例如說我已經測試了FIB(50000)爲最大= 4000,但只要我改變最大= 5000就停止工作。我打破了我的頭幾個小時,但仍然無法找出問題。

請告訴我我的代碼可能有什麼問題。

在導致運行時錯誤的代碼中是否有任何邏輯錯誤?

+2

你是否至少在調試器中運行它以知道它崩潰的位置? *它停止工作*或*它只是段故障*不是一個可靠的信息,以我們的調查爲基礎。 – 2012-03-10 19:15:35

+0

測試用例應該簡短並且直截了當。這段代碼當然不是。 – 2012-03-10 19:17:04

+0

我編譯它並在console中運行可執行文件。它顯示程序已停止工作,然後崩潰。 – 2012-03-10 19:17:22

回答

2

我認爲問題出在mul()函數中,因爲內部for循環中的索引k可以變成負整數,並且使用k來索引數組。

k總是遞減max - 1次,但僅在外部for循環的第一次迭代中設置爲max - 1。在外部for循環的後續迭代中,其設置爲小於max - 1的值,導致k變爲負值。

編輯:

我修改內for循環:

for(j=max-1;j>0;j--){ 
    if (k < 0) 
     std::cout << k << "\n"; 
    ... 
} 

並且當執行與許多負值期間提示被顯示供給14:因此這肯定是一個問題。

+0

感謝您的幫助。 – 2012-03-10 19:52:56

0

您與MAX較大值問題可能來自正在創建在棧上大型陣列,造成計算器的事實幹。

嘗試動態與new分配對象,看看SIGSEGV錯誤消失。