iMusic
iMusic

Reputation: 81

Why this function has segmentation fault?

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

#define E 1E-3

long double Fun(long double x);

int main() {
    long double a = 0;
    long double b = 1;
    long double temp;
    while(fabsl(a - b) > E){
        temp = a + b;
        temp = temp / 2;
        long double Funa = Fun(a);
        long double Funb = Fun(b);
        long double Funtemp = Fun(temp);

        if(Funtemp == 0){
            printf("temp = %Lf\n",temp);
            break;
        }

        if(Funtemp * Funa < 0){
            a = temp;
        }

        else if(Funtemp * Funb < 0) {
            b = temp;
        }
    }
    printf("a = %Lf\nb = %Lf", a, b);

    return 0;
}

long double Fun(long double x){
    return x*x*x + x*x - 1;
}

I don't know why the Fun() has segmentation fault? Really confused.

here are the information reported by clion below:

clion: 
Fun(a) = -var-create: unable to create variable object
Signal = SIGSEGV (Segmentation fault)

Upvotes: 2

Views: 148

Answers (1)

JohanC
JohanC

Reputation: 80574

Your segmentation fault could be caused by using long double on hardware that doesn't support it. Just try the same with double instead. On many platforms, including MSVC, double and long double use the same number of bits.

Another segmentation fault cause could be incompatible libraries working with long double, see for example this report in gcc on mingw. That would be the case if your segmentation fault happens when you try to execute fabsl.

Anyway, following code seems to not be doing what you expect:

    if(Funtemp * Funa < 0){
        a = temp;
    }
    else if(Funtemp * Funb < 0) {
        b = temp;
    }

This easily produces an endless loop.

You typically want Funa and Funb to always have opposite sign. So if Funa and Funtemp have opposite sign, you want to assign temp to b. And vice versa. Maybe also add a test in case all 3 have the same sign:

    if(Funtemp * Funa < 0){
        b = temp;
    }
    else if(Funtemp * Funb < 0) {
        a = temp;
    }
    else {
        printf("no solution possible\n");
        break;
    }

And, instead of stopping when the difference between a and b gets 1E-3, you could continue until temp gets equal to a or to b. a and b are moving very quickly towards each other, only getting into trouble when the (a+b)/2 step gets rounded to either a or b.

while(true){
    temp = a + b;
    temp = temp / 2;
    if (temp == a || temp == b)
        break;
    ...

Upvotes: 1

Related Questions