Quantcast
Channel: Active questions tagged gcc - Stack Overflow
Viewing all articles
Browse latest Browse all 22087

How can you fix the double free or corruption (out) Error in C in this occasion?

$
0
0

sadly I haven't been able to fix my issue, even after long searches online.

C - GNU GCC on Linux (the code works (sometimes) with mingw on Windows 10)

I have some structs, containing coefficients and values for a linear equation system.

I allocate them, work with them, don't change them, and want to free them in the end to allow a new runthrough.

I do however get a "double free or corruption (out)" in the marked code locations.

Does someone know how to fix this?

(I really am thinking about leaving a memory leak, since I wasted so much time on this...)

Thank you very much in advance!

typedef struct
{
    int n;
    double **data;
} Matrix;

typedef struct
{
    int n;
    double *data;
} Vector;

typedef enum
{
    JACOBI = 0,
    GAUSS_SEIDEL = 1
} Method;

typedef struct Listelement Listelement;

struct Listelement //list containing all results
{
    int n;
    Vector *dat;
    Listelement *next;
};

bool load(const char *filename, Matrix *A, Vector *b, Vector *x) 
{
    ...int row;
    //row = number of equations
    A->n = row;
    A->data = malloc(row * sizeof(double *));
    for (i = 0; i < row; i++)
    {
        A->data[i] = malloc(row * sizeof(double));
    }
    //Vektor b
    b->n = row;
    b->data = malloc(row * sizeof(double));
    //Vektor x
    x->n = row;
    x->data = malloc(row * sizeof(double));

    //structures are then looped over and filled with data
    //e.g.: sscanf(tok, "%lf", &out);
    //                A->data[j][i] = out;

    //sscanf(tok, "%lf", &out);
    //                b->data[j] = out;
}

//data in structures is only used for calculations and, except for vector x, never changed

int main(){
...Matrix *A;
    Vector *b;
    Vector *x;
...
        A = malloc(sizeof(Matrix));
        b = malloc(sizeof(Vector));
        x = malloc(sizeof(Vector));

if (load(filename, A, b, x)){
......
//after successful calculation: ask for user intentions on restarting and or stopping the application
            for (int k = 0; k < A->n; k++)
            {
                free(A->data[k]);     //ERROR on any other value than k=0!
            }

            free(A->data);
            A->n = 0;
            free(A);

            //free List
            Listelement *l1 = malloc(sizeof(Listelement));
            Listelement *l2 = malloc(sizeof(Listelement));
            l1 = result; //start with head
            while (l1 != l1->next) //iterate entire list
            {
                l2 = l1->next;
                free(l1->dat->data);
                l1->dat->n = 0;
                free(l1->dat);
                l1->n = 0;

                free(l1);
                l1 = l2;
            }

            //free Vectors
            free(x->data);     //ERROR crashed here for a bit, but not reproducable for me now
            x->n = 0;
            free(x);

            free(b->data);    //ERROR crashes here
            b->n = 0;
            free(b);
}

}



EDIT: Since requested, my entire code:

#include <stdio.h>
#include <stdbool.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>

#define _GNU_SOURCE

//für Umlaute in der Windowskonsole
/*
#define AE (unsigned char)142
#define ae (unsigned char)132
#define OE (unsigned char)153
#define oe (unsigned char)148
#define UE (unsigned char)154
#define ue (unsigned char)129
#define ss (unsigned char)225
*/

typedef struct
{
    int n;
    double **data;
} Matrix;

typedef struct
{
    int n;
    double *data;
} Vector;

typedef enum
{
    JACOBI = 0,
    GAUSS_SEIDEL = 1
} Method;

typedef struct Listelement Listelement;

struct Listelement //verkettete Liste zum Speichern der Ergebnisse
{
    int n; //anzahl der gespeicherten Vektoren (nur im Head aktuell)
    Vector *dat;
    Listelement *next;
};

bool load(const char *filename, Matrix *A, Vector *b, Vector *x) //csv Datei einlesen und Datenstrukturen allokieren und füllen
{

    char *str = malloc(sizeof(char) * 10000); //Einlesebuffer - 10000 Zeichen für sehr lange dateien als Grenze
    char *tok;                                //Zeichen zwischen den Kommas (eigentliche Werte)
    double out;                               //ausgelesener Wert
    int row = 0, col = -1, i, j;              //Anzahl der Zeilen & der Spalten in der Datei, zwei Laufvariablen
    bool lnempty;                             //Laufzeitcheck ob gelesene Zeile leer ist
    FILE *fp = fopen(filename, "r");

    if (fp == NULL)
    {
        printf("Die Datei %s konnte nicht gefunden werden\n", filename);
        return false;
    }

    while (fgets(str, 10000, fp) != NULL) //solange noch Zeilen eingelesen werden können
    {
        i = 0;
        lnempty = false;
        while (isspace(str[i])) //solange char at i whitespace ist - nächsten char checken
        {
            i++;
        }
        if (str[i] == '\0') //wenn alle chars außer das Ende whitespace sind - lnempty
            lnempty = true;

        if (!lnempty) //counting lines and validating file
        {
            i = 0;
            row++;
            tok = strtok(str, ","); //tok ist unterstring von , zu ,
            while (tok != NULL)
            {
                if (sscanf(tok, "%lf", &out) != 1) //überprüfen ob in double konvertiert werden kann
                {
                    printf("Fehler bei [%d][%d]!\n", row + 1, i + 1);
                    return false;
                }
                i++;
                tok = strtok(NULL, ","); //nächsten Wert zwischen den kommas einlesen
            }

            if (col == -1) //anfangswert auf aktuelle cols setzen
                col = i;

            if (i != col) //wenn cols nicht konstant - Fehler
            {
                printf("i:%d col:%d Das eingegebene GLS hat unterschiedlich viele Angaben pro Zeile!\n", i, col);
                return false;
            }
        }
    }

    if (!(col == row + 1 || col == row + 2) || row <= 0 || col <= 0) //berechenbare Form überprüfen
    {
        printf("Das eingegebene GLS ist nicht in der gewünschten Form!\n");
        return false;
    }

    //Matrix und Vektoren allocieren
    //Matrix
    A->n = row;
    A->data = malloc(row * sizeof(double *));
    for (i = 0; i < row; i++)
    {
        A->data[i] = malloc(row * sizeof(double));
    }
    //Vektor b
    b->n = row;
    b->data = malloc(row * sizeof(double));
    //Vektor x
    x->n = row;
    x->data = malloc(row * sizeof(double));

    //füllen
    j = 0;
    rewind(fp);                           //Datei wieder auf anfang zurücksetzen
    while (fgets(str, 10000, fp) != NULL) //gleiche Funktion wie zum checken, nur diesmal daten bereits in Strukturen schreiben
    {
        i = 0;
        lnempty = false;
        while (isspace(str[i]))
        {
            i++;
        }
        if (str[i] == '\0')
            lnempty = true;

        if (!lnempty)
        {
            tok = strtok(str, ",");
            i = 0;
            while (tok != NULL)
            {
                if (i <= row)
                {
                    sscanf(tok, "%lf", &out);
                    A->data[j][i] = out;
                }
                if (i == row)
                {
                    sscanf(tok, "%lf", &out);
                    b->data[j] = out;
                }
                if (i == row + 1)
                {
                    sscanf(tok, "%lf", &out);
                    x->data[j] = out;
                }
                i++;
                tok = strtok(NULL, ",");
            }
            if (col != row + 2)
            {
                x->data[j] = 0;
            }
            j++;
        }
    }

    fclose(fp);

    return true;
}

bool wantsrestart() //nachfragen ob der Nutzer das Programm neustarten möchte
{
    int m;
    m = -1;
    while (m != 0 && m != 1)
    {
        printf("Möchten Sie das Programm neu starten? (0=Nein, 1=Ja)\n");
        if (scanf("%d", &m) != 1)
        {
            m = -1;
        }
        while (getchar() != '\n'); //um scanf buffer zu clearen - bei Falscheingaben notwendig
    }
    printf("inrest\n");

    if (m != 0)
    {
        printf("inrest\n");
        return true;
    }
    return false;
}

Listelement *createlist(Vector *x) //verkettete Liste mit Vector x als erste Dateneingabe erstellen
{
    Listelement *head = malloc(sizeof(Listelement));
    Listelement *tail = malloc(sizeof(Listelement));
    head->dat = malloc(sizeof(Vector));
    head->dat->data = malloc((x->n) * sizeof(double));

    head->dat->n = x->n;
    for (int i = 0; i < x->n; i++)
    {
        head->dat->data[i] = x->data[i]; //Daten aus den Vektor in das erste Listenelement kopieren
    }

    head->next = tail;
    head->n = 1; //gibt Anzahl der gespeicherten Vektoren an

    tail->n = head->n; //tail.n ist immer 1
    tail->dat = 0;     //keine Daten im Tail speichern
    tail->next = tail; //tail verweist auf sich selbst

    return head;
}

Listelement *appendtolist(Listelement *head, Vector *x) //Vector x zur Liste hinzufügen
{
    Listelement *temp = malloc(sizeof(Listelement));
    temp->next = head;
    while (temp->next != temp)
    {
        temp = temp->next; //temp auf tail zuweisen
    }

    //Vector in Listelement kopieren
    temp->dat = malloc(sizeof(Vector));
    temp->dat->data = malloc(sizeof(double) * x->n);
    temp->dat->n = x->n;

    for (int i = 0; i < x->n; i++)
    {
        temp->dat->data[i] = x->data[i];
    }

    //neuen Tail anhängen
    Listelement *tail = malloc(sizeof(Listelement));
    temp->next = tail;
    tail->next = tail;
    head->n += 1; //Eintragscounter erhöhen

    return head;
}

void printlist(Listelement *head) //gesamte verkettete Liste auf den Bildschirm ausgeben
{
    Listelement *x;
    x = head;
    for (int i = 0; x != x->next; i++)
    {
        printf("%d:\n", i);
        for (int j = 0; j < x->dat->n; j++)
        {
            printf("x%d: %lf\n", j + 1, x->dat->data[j]);
        }
        printf("\n");
        x = x->next;
    }
}

void printlast(Listelement *head) //nur den letzen Eintrag der verketteten Liste auf den Bildschirm ausgeben
{
    Listelement *x;
    Vector *v;
    x = head;

    while (x->next != x)
    {
        v = x->dat;
        x = x->next;
    }

    if (head->n != -2) //Iterationsschritt nur ausgeben, wenn Iterationsgrenze nicht erreicht wurde
        printf("Iterationsschritt: %d\n", head->n);

    for (int i = 0; i < v->n; i++)
    {
        printf("x%d: %lf\n", i + 1, v->data[i]);
    }
}

bool islimit(Vector *x1, Vector *x2, double e) //überprüfen ob der neuberechnete Vector eine größere Differenz als e zum letzten hat
{
    double sum1 = 0, sum2 = 0;
    for (int i = 0; i < x1->n; i++)
    {
        sum1 += x1->data[i] * x1->data[i];
        sum2 += x2->data[i] * x2->data[i];
    }
    sum1 = sqrt(sum1);
    sum2 = sqrt(sum2);

    if (sum1 > sum2)
        return sum1 - sum2 < e;

    return sum2 - sum1 < e;
}

Listelement *solve(Method method, Matrix *A, Vector *b, Vector *x, double e) //GLS lösen - Rückgabe ist head der verketteten Liste
{
    int currit = 0;      //aktuelle Iteration
    int maxit = 100;     //maximale Iteration
    bool isdone = false; //check ob der Algorithmus schon gelöst ist
    double sum1;         //Zwischenwert für Berechnung

    //Zwischenspeicher um letzten Iterationsschritt zu speichern
    Vector *oldx = malloc(sizeof(Vector));
    oldx->n = x->n;
    oldx->data = malloc(sizeof(double) * oldx->n);

    Listelement *results = createlist(x); //Liste erstellen

    for (int i = 0; i < A->n; i++) //da 1/0 nicht definiert:
    {
        if (A->data[i][i] == 0) //wenn ... nicht berechenbar
        {
            results->n = -1; //Fehlercode für UI ausgabe
            return results;
        }
    }

    if (method == JACOBI) //Jacobi Algorithmus
    {
        while (currit < maxit && !isdone) //solange rechnen bis entweder keine Iterationen mehr und noch nicht gelöst
        {
            for (int i = 0; i < x->n; i++) //oldx füllen
            {
                oldx->data[i] = x->data[i];
            }

            for (int i = 0; i < x->n; i++)
            {
                sum1 = b->data[i];

                for (int j = 0; j < x->n; j++)
                {
                    if (j != i)
                    {
                        sum1 -= A->data[i][j] * oldx->data[j]; //sum1 = b(i)-(A(i,j)-oldx(j)) => für 0<i,j<x->n
                    }
                }
                x->data[i] = sum1 / A->data[i][i]; //neuen Wert berechnen
            }

            results = appendtolist(results, x); //wenn alle Zeilen berechnet - neuen Vektor hinzufügen

            if (islimit(oldx, x, e)) //wenn Limit erreicht - Ergebnis ausgeben
                return results;

            currit++;
        }

        results->n = -2;
        return results; //keine Iterationen mehr
    }

    if (method == GAUSS_SEIDEL) //Gauß-Seidel-Algorithmus -- gleiches wie Jacobi, nur neue Werte verwenden wenn verfügbar
    {
        while (currit < maxit && !isdone)
        {
            for (int i = 0; i < x->n; i++)
            {
                oldx->data[i] = x->data[i];
            }

            for (int i = 0; i < x->n; i++)
            {
                sum1 = b->data[i];

                for (int j = 0; j < x->n; j++)
                {
                    if (j < i)
                    {
                        sum1 -= A->data[i][j] * x->data[j]; //wenn bereits berechnet - neue Daten verwenden
                    }

                    if (j > i)
                    {
                        sum1 -= A->data[i][j] * oldx->data[j];
                    }
                }
                x->data[i] = sum1 / A->data[i][i];
            }

            results = appendtolist(results, x);

            if (islimit(oldx, x, e))
                return results;

            currit++;
        }
        results->n = -2;
        return results;
    }

    results->n = -1;
    return results; //Fehlerstate - bei unbekannten Fehlern behandeln wie unberechenbar
}

int main() //Hauptfunktion => Userinput verarbeiten
{
    Method method;
    int m;
    double e;
    bool status = true;
    char filename[256];
    Matrix *A;
    Vector *b;
    Vector *x;
    Listelement *result;

    while (status)
    {
        A = malloc(sizeof(Matrix));
        b = malloc(sizeof(Vector));
        x = malloc(sizeof(Vector));

        printf("Dateinamen bitte eingeben:\n");
        scanf("%s", filename);

        if (load(filename, A, b, x))
        {
            printf("Datei erfolgreich eingelesen!\n");
            m = -1;
            while (m != JACOBI && m != GAUSS_SEIDEL)
            {
                printf("Welchen Algorithmus möchten Sie verwenden? (0: Jakobi; 1: Gauß-Seidel)\n");
                if (scanf("%d", &m) != 1)
                {
                    m = -1;
                }
                while (getchar() != '\n')
                    ; //um scanf buffer zu clearen - bei Falscheingaben notwendig
            }
            method = m;

            e = -1;
            while (e < 0)
            {
                printf("Wie groß möchten Sie ihre Fehlerschranke wählen? (double > 0)\n");
                if (scanf("%lf", &e) != 1)
                {
                    e = -1;
                }
                while (getchar() != '\n')
                    ; //um scanf buffer zu clearen - bei Falscheingaben notwendig
            }

            result = solve(method, A, b, x, e);

            switch (result->n)
            {

            case -1:
                printf("Das gewählte LGS enthält 0 in der Hauptdiagonale und kann daher mit den Algorithmen nicht berechnet werden!\n");
                break;
            case -2:
                printf("Der Berechenvorgang erreichte 100 Iterationen und wurde daher abgebrochen!\n");
                m = -1;
                while (m != 0 && m != 1)
                {
                    printf("Möchten Sie trotzdem alle Werte, oder nur den Vektor x ausgeben?(0=alle Vektoren oder 1=nur der letzte Vektor)\n");
                    if (scanf("%d", &m) != 1)
                    {
                        m = -1;
                    }
                    while (getchar() != '\n')
                        ; //um scanf buffer zu clearen - bei Falscheingaben notwendig
                }

                if (m == 0)
                {
                    printlist(result);
                }
                else
                {
                    printlast(result);
                }
                break;
            default:
                printf("Berechnung erfolgreich!\n");
                m = -1;
                while (m != 0 && m != 1)
                {
                    printf("Möchten Sie alle Werte, oder nur den Vektor x ausgeben?(0=alle Vektoren oder 1=nur der letzte Vektor)\n");
                    if (scanf("%d", &m) != 1)
                    {
                        m = -1;
                    }
                    while (getchar() != '\n')
                        ; //um scanf buffer zu clearen - bei Falscheingaben notwendig
                }

                if (m == 0)
                {
                    printlist(result);
                }
                else
                {
                    printlast(result);
                }
                break;
            }

            status = wantsrestart(); //Neustartintention abfragen
            printf("test0");

            //free Matrix

            //free(A->data[1]);
/*
            for (int k = 0; k < A->n; k++)
            {
                free(A->data[k]);
            }
*/
            printf("test");
            free(A->data);
            printf("test2");
            A->n = 0;
            free(A);
            printf("test3");

            //free List
            Listelement *l1 = malloc(sizeof(Listelement));
            Listelement *l2 = malloc(sizeof(Listelement));
            l1 = result; //mit head beginnen
            while (l1 != l1->next) //ganze Liste iterieren
            {
                l2 = l1->next;
                free(l1->dat->data);
                l1->dat->n = 0;
                free(l1->dat);
                l1->n = 0;

                free(l1);
                l1 = l2;
                printf("test4");
            }
            //free Vectors
            free(x->data);
            x->n = 0;
            free(x);

            free(b->data);
            b->n = 0;
            free(b);
        }
        else
        {
            free(A);
            free(x);
            free(b);
            printf("Dateifehler!\n");
            status = wantsrestart(); //Neustartintentionen abfragen
        }
    }

    return 0; //Programmende
}



Viewing all articles
Browse latest Browse all 22087

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>