Alokowanie pamięci (tworzenie macierzy 2-wymiarowej).

0

Witam mam pewien problem, mam funkcje która tworzy macierz[n][m], jedna podczas kompilacji zwraca mi terminate called after throwing an instance of 'std::bad_alloc'
what(): std::bad_alloc

Czy ja alokuje za dużo, i jak to naprawić (chodzi mi o funkcje create_matrix)

const long double x_min = 0.0;
const long double x_max = 1.0;
const long double t_min = 0.0;
const long double t_max = 0.5;
const long double e_lambda = 0.4;
const long double i_lambda = 1.0;
const int D = 1;
long double h = 0.01;

long double *create_vector(unsigned int n) {
    return new long double[n];
}

void delete_vector(const long double *v) {
    delete[] v;
}

long double **create_matrix(unsigned int n, unsigned int m) {
    long double **matrix = new long double *[n];
    for (unsigned int i = 0; i < n; ++i)
        matrix[i] =  new long double[m];
    return matrix;
}

void delete_matrix(long double **matrix, unsigned int n) {

    for (unsigned int i = 0; i < n; ++i)
        delete[] matrix[i];
    delete[] matrix;
}

long double vector_max(const long double *vector, unsigned int n) {
    long double max = vector[0];
    for (unsigned int i = 1; i < n; ++i) {
        if (vector[i] > max)
            max = vector[i];
    }
    return max;
}

long double **get_errors(long double **realSolution, long double **numericalSolution,
                         unsigned int n, unsigned int m) {
    long double **errors = create_matrix(n, m);
    for (unsigned int i = 0; i < n; ++i) {
        for (unsigned int j = 0; j < m; ++j)
            errors[i][j] = fabs(realSolution[i][j] - numericalSolution[i][j]);
    }
    return errors;
}

long double *get_max_errors(long double **realSolution, long double **numericalSolution,
                            unsigned int n, unsigned int m) {
    long double **errors = get_errors(realSolution, numericalSolution, n, m);
    long double *max_errors = create_vector(n);
    for (unsigned int i = 0; i < n; ++i) {
        max_errors[i] = vector_max(errors[i], m);
    }
    delete_matrix(errors, n);
    return max_errors;
}

void save_vectors_to_file(double long **vectors, int n, int m, string filename) {
    fstream file(filename.c_str(), ios::out);
    if (file.is_open()) {
        for (int i = 0; i < m; ++i) {
            for (int j = 0; j < n; ++j) {
                file << vectors[j][i] << ' ';
            }
            file << endl;
        }
        file.close();
    }
}

long double *log10_vector(long double number, unsigned int n, long double div = 10.0) {
    long double *v = create_vector(n);
    for (unsigned int i = 0; i < n; ++i) {
        v[i] = log10(number);
        number /= div;
    }
    return v;
}

long double *get_steps(long double start, long double d, unsigned int n) {
    long double *v = create_vector(n);
    long double x = start;
    for (unsigned int i = 0; i < n; ++i) {
        v[i] = x;
        x += d;
    }
    return v;
}

long double analytical_equation(double x, double t) {

    return exp(-(M_PI * M_PI) * D * t) * sin(M_PI * x);
}

long double get_dt(long double lambda) {
    return (lambda * h * h) / D;
}

void init(long double **A, unsigned int n, unsigned int m) {
    for (unsigned int i = 0; i < m; ++i) {
        A[0][i] = sin(M_PI * h * i);
    }
    for (unsigned int i = 0; i < n; ++i) {
        A[i][0] = 0.0;
        A[i][m - 1] = 0.0;
    }
}

void thomas(const long double *l, long double *d, const long double *u, long double *b, long double*x, unsigned int n) {
    for (unsigned int i = 1; i < n; ++i) {
        d[i] = d[i] - l[i - 1] * (u[i - 1] / d[i - 1]);
    }
    for (unsigned int i = 1; i < n; ++i) {
        b[i] = b[i] - l[i - 1] * b[i - 1] / d[i - 1];
    }
    x[n - 1] = b[n - 1] / d[n - 1];
    for (int i = n - 2; i >= 0; --i) {
        x[i] = (b[i] - u[i] * x[i + 1]) / d[i];
    }
}

long double **analytical_method(unsigned int n, unsigned int m, long double dt) {
    long double **A = create_matrix(n, m);
    init(A, n, m);

    long double x, t = t_min;
    for (unsigned int i = 0; i < n; ++i) {
        x = x_min;
        for (unsigned int j = 0; j < m; ++j) {
            A[i][j] = analytical_equation(x, t);
            x += h;
        }
        t += dt;
    }
    return A;
}

long double **simple_explicit_method(unsigned int n, unsigned int m, long double lambda) {
    long double **A = create_matrix(n, m);
    init(A, n, m);
    for (unsigned int i = 0; i < n - 1; ++i) {
        for (unsigned int j = 1; j < m - 1; ++j) {
            A[i + 1][j] = A[i][j] + lambda * (A[i][j + 1] - 2 * A[i][j] + A[i][j - 1]);
        }
    }
    return A;
}

long double **laasonen_method(unsigned int n, unsigned int m, long double lambda) {
    long double **A = create_matrix(n, m);
    init(A, n, m);
    long double llambda = 1.0 + 2.0 * lambda;
    long double *l = create_vector(m), *d = create_vector(m), *u = create_vector(m),
            *b = create_vector(m), *x = create_vector(m);
    for (unsigned int k = 1; k < n; ++k) {
        l[0] = 0.0;
        d[0] = 1.0;
        u[0] = 0.0;

        b[0] = A[k - 1][0];
        for (unsigned int i = 1; i < m - 1; ++i) {
            l[i] = lambda;
            d[i] = -llambda;
            u[i] = lambda;
            b[i] = -A[k - 1][i];
        }
        l[m - 1] = 0.0;
        d[m - 1] = 1.0;
        u[m - 1] = 0.0;
        b[m - 1] = 0.0;
        thomas(l, d, u, b, x, m);
        for (unsigned int i = 1; i < m - 1; ++i) {
            A[k][i] = x[i];
        }
    }
    delete_vector(l);
    delete_vector(d);
    delete_vector(u);
    delete_vector(b);
    delete_vector(x);
    return A;
}

void solve_for_h(long double **(*method)(unsigned int, unsigned int, long double), long double lambda, string name, long double h_start = 0.25, unsigned int q = 3) {
    h = h_start;
    long double dt;
    unsigned int n, m;
    long double **analytical_results, **method_results, **errors, *max_errors, *tmax_errors
            = create_vector(q);
    long double **save_vectors = new long double *[2];
    save_vectors[0] = log10_vector(h_start, q);
    save_vectors[1] = tmax_errors;

    string fullname("errors_tmax_");
    fullname += name;
    for (unsigned int i = 0; i < q; ++i) {
        long double dt = get_dt(lambda);
        unsigned int n = (t_max - t_min) / dt;
        unsigned int m = (x_max - x_min) / h;
        h = (x_max - x_min) / m;
        analytical_results = analytical_method(n, m, dt);
        method_results = method(n, m, lambda);

        max_errors = get_max_errors(analytical_results, method_results, n, m);
        tmax_errors[i] = log10(max_errors[n - 1]);
        delete_matrix(analytical_results, n);
        delete_matrix(method_results, n);
        delete_vector(max_errors);
        h /= 10.0;
    }
    save_vectors_to_file(save_vectors, 2, q, fullname);
    delete_matrix(save_vectors, 2);
}

void solve_for_t(long double **(*method)(unsigned int, unsigned int, long double), long double lambda, string name, long double h_start = 0.01) {
    h = h_start;
    long double dt = get_dt(lambda);
    unsigned int n = (t_max - t_min) / dt + 1;
    unsigned int m = (x_max - x_min) / h + 1;
    h = (x_max - x_min) / m;
    string fullname("results_"), fullname2("errors_max_");
    fullname += name;
    fullname2 += name;
    long double **analytical_results = analytical_method(n, m, dt);
    long double **method_results = method(n, m, lambda);
    long double **errors = get_errors(analytical_results, method_results, n, m);
    long double *max_errors = get_max_errors(analytical_results, method_results, n, m);

    long double **save_vectors = new long double *[3], **save_vectors2 = new long
    double *[2];
    save_vectors[0] = get_steps(x_min, h, n);
    save_vectors[1] = analytical_results[n - 1];
    save_vectors[2] = method_results[n - 1];
    save_vectors2[0] = get_steps(t_min, dt, n);
    save_vectors2[1] = max_errors;
    save_vectors_to_file(save_vectors, 3, m, fullname);
    save_vectors_to_file(save_vectors2, 2, n, fullname2);
    delete_matrix(analytical_results, n);
    delete_matrix(method_results, n);
    delete_matrix(errors, n);
    delete_matrix(save_vectors2, 2);
    delete_vector(save_vectors[0]);
    delete save_vectors;
}

int main() {
    solve_for_h(simple_explicit_method, e_lambda, "sem", 0.5);
    solve_for_h(laasonen_method, i_lambda, "laasonen", 0.5);
    solve_for_t(simple_explicit_method, e_lambda, "sem", 0.0025);
    solve_for_t(laasonen_method, i_lambda, "laasonen", 0.0025);
    cout << "Uruchomiono\n";

    return 0;
}



0

@Justice Beaver:

Musisz pisać w C z new? Tego (mi) się totalnie nie chce czytać.
Nie możesz w prawdziwym C++ ?

1

bad_alloc oznacza że zabrakło ci pamięci, prawdopodobnie zapominasz coś zwolnić.
Zacznij pisać w C++: klasa z konstruktorem i destruktorem.
Użyj vector<> który na 100% przetestowany i nie zapomni się zwolnić.

3

U mnie program działa, chodź w pewnym momencie aplikacja sobie alokuje około w ~5GB ramu, może ci po prostu ramu zabrakło.

solve_for_t(simple_explicit_method, e_lambda, "sem", 0.0025); alokuje te 5GB, ale potem wszystko ładnie zwalnia

1

https://dsp.krzaq.cc/post/176/ucze-sie-cxx-kiedy-uzywac-new-i-delete/

Szalony Programista2 napisał(a):

U mnie program działa, chodź w pewnym momencie aplikacja sobie alokuje około w ~5GB ramu, może ci po prostu ramu zabrakło.

solve_for_t(simple_explicit_method, e_lambda, "sem", 0.0025); alokuje te 5GB, ale potem wszystko ładnie zwalnia

Pewnie zbudował program do 32 bitów (domyślne ustawienie w niektórych miejscach), gdzie limit to 2.5GB

Swoją drogą co to konkretnie robi, że zjada aż 5GB? To mi wygląda na zły dobór parametrów.

0
Szalony Programista2 napisał(a):

U mnie program działa, chodź w pewnym momencie aplikacja sobie alokuje około w ~5GB ramu, może ci po prostu ramu zabrakło.

Malo ramu nie spowoduje bad_alloc. Ale malo ramu i brak swapa juz tak. Jesli swap jest to objaw bedzie taki:

ale potem wszystko ładnie zwalnia

1 użytkowników online, w tym zalogowanych: 0, gości: 1