Что вызывает Ошибку сегментирования и как это исправить?

#include <stdio.h>
#include <math.h>

unsigned int fact(int n){
    unsigned int res = 1;
    for (int i = 2;i <= n; i++){
        res *= i;
    }
    return res;
}

double absolute(double i){
    if (i < 0){return -i;} else {return i;}
}

void main(void){
    double acc,curr,diff;
    int n = 1;
    printf("Input accuracy: ");
    do{
    scanf("%lf\n",acc);
    } while (acc <= 0);
    diff = 155;
    while(absolute(diff) >= acc){
        diff = pow(2,n)/fact(n);
        curr += diff;
        n += 1;
    }
    printf("%lf with %d members\n",&curr,&n);
}

Что-то в этом коде вызывает ошибку сегментирования. Дословно "Ошибка сегментирования (образ памяти сброшен на диск)". Найденные мной ответы объясняли, что проблема заключается в попытке обратиться к разделу памяти, к которому нету доступа (как например при попытке получить n-ый элемент в массиве длиной n). Однако у меня никаких обращений к памяти кроме scanf и printf нету. Cижу в VS code с установленным gcc на Fedora Linux 40.


Ответы (1 шт):

Автор решения: Harry

Начнем с того, что в scanf указывается адрес, куда надо записать значение, а в printf — напротив, значение, которое надо вывести. Это к конкретному вашему вопросу. Сейчас у вас попытка записать введенное значение по адресу, в который преобразуется (кстати, неопределенное) значение acc, приводит к обращению, как вы верно написали,

к разделу памяти, к которому нету доступа

Кстати, компилятор должен был неоднократно предупредить вас о неприятностях... Предупреждал?

Далее, судя по коду, вы считаете

введите сюда описание изображения

Если, конечно, не ошиблись и считать надо не от n == 0. Но при этом для достижения большой точности могут потребоваться большие факториалы, которые вызовут переполнение. Все члены ряда положительные, так что искать значение по модулю не надо, тем более писать свою функцию, а не пользоваться стандартной fabs. Считать каждый очередной член проще из предыдущего.

Словом, если категорически нельзя писать просто и точно :)

int main() { printf("%lf\n",exp(2)-1); }

(кстати, функция main обязана возвращать int, а не void!), то я бы написал примерно так:

#include <stdio.h>
#include <math.h>

int main()
{
    double acc, sum = 0, term = 1;
    int n = 0;
    do  // Заметим, что это защита ТОЛЬКО от ввода отрицательного числа,
    {   // но не, например, строки символов, словом, не-числа.
        printf("Input accuracy (>0): ");
        scanf("%lf",&acc);
    } while (acc <= 0);
    while(term >= acc)
    {
        sum += term *= 2./++n;
        printf("term = %lf  sum = %lf\n", term,sum);
    }
    printf("%lf with %d members\n",sum,n);
}

Кстати, в этом коде вы видите правильное использование scanf и printf.

→ Ссылка