Segmentation fault вместо адекватной работы в C

Рейтинг: 0Ответов: 2Опубликовано: 17.04.2023

У меня есть программа на С, которая почему-то выдаёт Segmentation fault вместо нормальной работы.

Я догадываюсь, что пожалуй вышло переполнение в памяти, однако я не понимаю, почему оно возникло и как его исправить. Код моей программы:

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

int ncd(unsigned long long x, unsigned long long y) {
    unsigned long long c;
    if (y > x) {
        c = x;
        x = y;
        y = c;
    };
    unsigned long long n = y;
    while (x%y) {
        c = x;
        x = y;
        y = c % y;
    };
    return y;
}


unsigned long long raiseTo(unsigned long long base, unsigned long long power){
    unsigned long long result = 1,i;
    for (i=0; i<power;i++) {
        result*=base;
    }
    return result;
}

unsigned long long properDivisorSum(unsigned long long n, long k, long z){
    unsigned long long prod = 1; 
    unsigned long long temp = n,i,count = 0;

    if (ncd(n, z) > 1) return 1;
    while(n%2 == 0){
        count++;
        n /= 2;
    }
    
    if(count!=0)
        prod *= (raiseTo(2,count + 1) - 1);

    for(i=3;i*i<=n;i+=2){
        count = 0;
        
        while(n%i == 0){
            count++;
            n /= i;
        }
        
        if(count==1)
            prod *= (i+1);
        else if(count > 1)
            prod *= ((raiseTo(i,count + 1) - 1)/(i-1));
    }
    
    if(n>2)
        prod *= (n+1);

    if (prod % z) return 1;
    return (prod / z * k) - temp;
}

void printSeries(unsigned long long* arr,int size,long k,long z,char* type){
    if ((type != "Sociable") && (type != "Cyclic")) return;
    if ( arr[size-1] == arr[size-3] ) return;
    int i;
    
    printf("\nInteger : %llu, Type : %s, Parameter1 : %llu, Parameter2 : %llu, Series : ",arr[0],k,z,type);
    
    for(i=0;i<size-1;i++)
        printf("%llu, ",arr[i]);
    printf("%llu\n",arr[i]);
}

void aliquotClassifier(unsigned long long n, long k, long z){
    unsigned long long arr[16];
    int i,j;
    
    arr[0] = n;
    
    for(i=1;i<16;i++){
        arr[i] = properDivisorSum(arr[i-1], k, z);
        
        if(arr[i]==0||arr[i]==n||(arr[i]==arr[i-1] && arr[i]!=n)){
            printSeries(arr,i+1,k,z,(arr[i]==0)?"Terminating":(arr[i]==n && i==1)?"Perfect":(arr[i]==n && i==2)?"Amicable":(arr[i]==arr[i-1] && arr[i]!=n)?"Aspiring":"Sociable");
            return;
        }
        
        for(j=1;j<i;j++){
            if(arr[j]==arr[i]){
                printSeries(arr,i+1,k,z,"Cyclic");
                return;
            }
        }
    }
    
}

int main()
{
    long k = 3;
    while (1) {
        for (long z = k/2; z < k; z++) {
            if (z*2 <= k) continue;
            if (ncd(k, z) > 1) continue;
            if (properDivisorSum(z, 1, 1) > k - z) continue;
            for (long i = 1; i < 1000000; i++) {
                if (ncd(i, z) > 1) continue;
                aliquotClassifier(i, k, z);
            };
        };
        k = k + 1;
    };
}

При нормальной работе программа должна подумать достаточно времени и написать что-то типо "Integer : ..., Type : Sociable, Parameter1 : 11, Parameter2 : 7, Series : ...".

Заранее благодарен за помощь!

Ответы

▲ 2

В функции aliquotClassifier вы создаёте массив arr на 16 элементов, затем передаёте его и i+1 в функцию printSeries. Внутри printSeries вы вызываете arr[size-3]. При i=1 это выражение вам даст -2, т.е. вы косвенно обратились к элементу массива arr[-2].

PS. При переполнении памяти стека, у вас будет сигнал stackoverflow. При переполнении кучи у вас вылетит исключение "бэд алокейт", либо вернёт код ошибки, если вы аллоцировали память через функцию, которая не бросает исключения. Сигфолл возникает только тогда, когда вы залезли не в свою область памяти. Например, когда обратились по неправильному элементу массива, или прыгнули по указателю на ранее неаллоцированный кусок памяти.

▲ 0

Я разобрался сам. Короче, проблема была в этой строчке:

printf("\nInteger : %llu, Type : %s, Parameter1 : %llu, Parameter2 : %llu, Series : ",arr[0],k,z,type);

Дело в том, что я пытался вывести k, которое является числом, как строку, что и дало Segmentation fault..