Malloc ошибка освобождения памяти - C (СИ)
Формулировка задачи:
ЧЯДНТ? Косяк такой:
heap corruption detected before normal block (№0) at 0x...
CRT detected that the application wrote to memory before start of heap buffer.
double SizeArr = 5, wData = 8, **Arr0, *Arr1, *Arr2; Len = SizeArr * sizeof(double); Arr0 = (double**)malloc(SizeArr * sizeof(*Arr0)); for (i = 0; i < SizeArr; ++i) Arr[i] = (double*)malloc(Len); Arr1 = (double*)malloc(Len); Arr2 = (double*)malloc(Len); for (i = 0; i < SizeArr; ++i) Arr[i] = (double*)realloc(Arr[i], wData * sizeof(*Arr)); free(Arr1); Arr1 = NULL; // нет ошбки free(Arr2); Arr2 = NULL; // ошибка for (i = 0; i < SizeArr; ++i) free(Arr0[i]); // ошибка - срабатывание точки останова free(Arr0); Arr0 = NULL;
Код целиком
#include <math.h> #include <stdio.h> #include <iostream> #include <ctime> void mxmt(double **Data, double **Arr, size_t wData, size_t SizeArr); void tred2(double **Arr, size_t SizeArr, double *D0, double *D1); void tqli1(double **Arr, size_t SizeArr, double *D0, double *D1, size_t *MaxIter); void bevm(double **Arr, size_t SizeArr, double *D0, double *D1, double **DT); void ivm(double **DT, double *D0, size_t SizeArr); void vxb(double *A, double **B, double **C, size_t whM, size_t wB); void smdd(double **C, double *D0, size_t SizeArr); void axb(double **A, double **B, double **C, size_t hA, size_t whM, size_t wB); void output1(double *D, size_t SizeArr); void output2i(double **Arr, size_t SizeArr); void output2t(double **Arr, size_t SizeArr); void output2r(double **Arr, size_t SizeArr, size_t wData); void output2rt(double **Arr, size_t SizeArr, size_t wData); int main() { setlocale(0, "ru-ru"); srand((size_t)time(0)); double **Data, **Arr, **DT, *D0, *D1, **SU; size_t i, SizeArr = 5, wData = 8, Len, *MaxIter = &i; Len = wData * sizeof(**Data); Data = (double**)malloc(SizeArr * sizeof(*Data)); for (i = 0; i < SizeArr; ++i) Data[i] = (double*)malloc(Len); for (i = 0; i < SizeArr; ++i) for (size_t j = 0; j < wData; ++j) Data[i][j] = 5 - rand() % 11; Len = SizeArr * sizeof(double); Arr = (double**)malloc(SizeArr * sizeof(*Arr)); for (i = 0; i < SizeArr; ++i) Arr[i] = (double*)malloc(Len); mxmt(Data, Arr, wData, SizeArr); puts("Исходные данные (Data): "); output2r(Data, SizeArr, wData); puts("Исходная левая симметричная матрица (Data x Data^T): "); output2i(Arr, SizeArr); D0 = (double*)malloc(Len); //memset(&D0[0], 0, Len); D1 = (double*)malloc(Len); //memset(&D1[0], 0, Len); DT = (double**)malloc(3 * sizeof(**DT)); for (i = 0; i < 3; i++) DT[i] = (double*)malloc(Len); tred2(Arr, SizeArr, D0, D1); for (i = 0; i < SizeArr; ++i) { DT[0][i] = D0[i]; DT[1][i] = D1[i]; } i = 30; tqli1(Arr, SizeArr, D0, D1, MaxIter); for (i = 0; i < SizeArr; ++i) DT[2][i] = D0[i]; puts("Собственные значения (L): "); output1(D0, SizeArr); bevm(Arr, SizeArr, D0, D1, DT); puts("Собственные векторы (V): "); output2t(Arr, SizeArr); ivm(DT, D0, SizeArr); puts("Обратный вектор сингулярных значений (S'): "); output1(D0, SizeArr); // Arr = D0 x Arr x Data [ V^(T) = (S^(T))^(-1) x U^(T) x A ] SU = (double**)malloc(SizeArr * sizeof(**SU)); for (i = 0; i < SizeArr; i++) SU[i] = (double*)malloc(Len); // используем формулу умножения вектора на не транспонированную матрицу, // поскольку её содежимое уже транспонировано vxb(D0, Arr, SU, SizeArr, SizeArr); //output2t(SU, SizeArr); smdd(SU, D0, SizeArr); //output2t(SU, SizeArr); for (i = 0; i < SizeArr; ++i) Arr[i] = (double*)realloc(Arr[i], wData * sizeof(*Arr)); axb(SU, Data, Arr, SizeArr, SizeArr, wData); puts("Матрица векторов (V), нулевые вектора опущены: "); output2rt(Arr, wData, SizeArr); system("pause"); for (i = 0; i < SizeArr; ++i) free(Data[i]); free(Data); Data = NULL; for (i = 0; i < SizeArr; ++i) free(SU[i]); free(SU); SU = NULL; for (i = 0; i < 3; ++i) free(DT[i]); free(DT); DT = NULL; free(D0); D0 = NULL; //free(D1); //D1 = NULL; for (i = 0; i < SizeArr; ++i) free(Arr[i]); //free(Arr); Arr = NULL; return 0; } void mxmt(double **Data, double **Arr, size_t wData, size_t SizeArr) { for (size_t i = 0; i < SizeArr; ++i) for (size_t j = i; j < SizeArr; ++j) { Arr[j][i] = 0.; for (size_t k = 0; k < wData; ++k) Arr[j][i] += Data[i][k] * Data[j][k]; Arr[i][j] = Arr[j][i]; } } void tred2(double **Arr, size_t SizeArr, double *D0, double *D1) { size_t i, j, k, l; double Scale, Sum, Pre, HH; /* получение ортогональной матрицы трансформации */ /* проход по стадиям/итерациям процесса редукции */ for (i = SizeArr - 1; i > 0; --i) { l = i - 1; D0[i] = Scale = 0.; /* вычислить сумму модулей строки под главной диагональю */ for (j = 0; j < i; ++j) Scale += fabs(Arr[i][j]); /* сложный процесс везде, кроме последней стадии/итерациям, весь обрабатываемый диапазон находится под главной диагональю матрицы */ if (i < 2 || !Scale) D1[i] = Arr[i][l]; else { /* преобразование матрицы */ /* масштабируем строку */ for (j = 0; j < i; ++j) Arr[i][j] /= Scale; /* вычислить сумму квадратов строки */ for (j = 0; j < i; ++j) D0[i] += Arr[i][j] * Arr[i][j]; /* работаем с вектором U */ D1[i] = (Arr[i][l] < 0. ? sqrt(D0[i]) : -sqrt(D0[i])); D0[i] -= Arr[i][l] * D1[i]; Arr[i][l] -= D1[i]; D1[i] *= Scale; /* вычисляем предварительный коэффициент Pre */ for (Pre = 0., j = 0; j < i; ++j) { Arr[j][i] = Arr[i][j] / D0[i]; for (Sum = 0., k = 0; k <= j; ++k) Sum += Arr[j][k] * Arr[i][k]; for (k = j + 1; k < i; ++k) Sum += Arr[k][j] * Arr[i][k]; D1[j] = Sum / D0[i]; Pre += Arr[i][j] * D1[j]; } /* трансформируем матрицу */ HH = Pre / (D0[i] + D0[i]); for (j = 0; j < i; ++j) { D1[j] -= HH * Arr[i][j]; for (k = 0; k <= j; ++k) Arr[j][k] -= (D1[k] * Arr[i][j] + D1[j] * Arr[i][k]); } } } /* сохраняем главную диагональ */ for (D1[0] = 0., i = 0; i < SizeArr; ++i) D0[i] = Arr[i][i]; /**/ } void tqli1(double **Arr, size_t SizeArr, double *D0, double *D1, size_t *MaxIter) { size_t i, j, k, Iter; double b, c, DD, f, g, p, r, s; /* сдвигаем массив влево для удобства */ for (i = 1; i < SizeArr; ++i) D1[i - 1] = D1[i]; D1[i - 1] = 0.; for (i = 0; i < SizeArr; ++i) { Iter = *MaxIter; do { /* диагонализируем миноры с текущей строки */ /* находим малый поддиагональный элемент для расщепления */ for (j = i; j < SizeArr - 1; ++j) { DD = fabs(D0[j]) + fabs(D0[j + 1]); if ((double)(fabs(D1[j] + DD)) == DD) break; } /* если верхний левый угол минора еще не диагональный */ if (j != i) { /* формирование сдвига */ g = (D0[i + 1] - D0[i]) / (2. * D1[i]); r = hypot(1., g); /* находим сумму модулей d_m и k_s с сохранением исходного знака */ g += (g >= 0. ? fabs(r) : -fabs(r)); g = D0[j] - D0[i] + D1[i] / g; /* плоская ротация оригинального QL алгоритма, сопровождаемая ротациями Гивенса для восстановления трехдиагональной формы */ for (s = c = 1., p = 0., k = j - 1; k < j && k >= i; --k) { f = s * D1[k]; b = c * D1[k]; D1[k + 1] = r = hypot(f, g); if (r == 0.) { D0[k + 1] -= p; D1[j] = 0.; break; } /* основные действия на ротации */ s = f / r; c = g / r; g = D0[k + 1] - p; r = (D0[k] - g) * s + 2. * c * b; p = s * r; D0[k + 1] = g + p; g = c * r - b; } /* безусловный переход к новой итерации при нулевом знаменателе и недоведенной до конца последовательности ротаций */ if (r == 0. && k < j && k >= i) continue; /* сохраняем новые значения диагоналей */ D0[i] -= p; D1[i] = g; D1[j] = 0.; } } while (j != i && --Iter); if (!Iter) { printf("Привышен заданный порог итераций на цикле %d \n", i); break; } } } void bevm(double **Arr, size_t SizeArr, double *D0, double *D1, double **DT) { double Div, Delta; size_t i, j, k, l, Rang; // цикл поиска сбственных векторов для каждого собственого значения for (i = 0; i < SizeArr; ++i) { // получаем главную и прилигающие к ней диагонали for (j = 0; j < SizeArr; ++j) { D0[j] = DT[0][j] - DT[2][i]; D1[j - 1] = DT[1][j]; } // получаем триугольную/трапциидальную матрицу из трёхдиагональной Div = 1.; Rang = l = SizeArr - 1; D1[l] = D1[0]; for (j = 0, k = 1; k < l; ++j, ++k) { D0[k] = (D0[j] * D0[k] - D1[l] * D1[j]) / Div; D1[l] = D1[k]; D1[k] = D0[j] / Div * D1[k]; Div = D0[j]; } // подсчитываем среднюю линейную погрешность с некоторым запасом // кого это не устраивает - считает погрешность как положено D0[k] = (D0[j] * D0[k] - D1[l] * D1[j]) / Div; Delta = 1.00059 * D0[k]; Div = D0[k] / k; D0[k] = 1.; // поиск свободных значений / подсчёт ранга матрицы for (j = SizeArr - 2; j; --j, Delta -= Div) if (fabs(D0[j]) < Delta && fabs(D1[j]) < Delta) { D0[j] = 1.; --Rang; } else break; // получаем собственный вектор для текущего собственного значения for (j = Rang - 1, k = Rang; j < Rang; --j, --k) D0[j] = -D0[k] / D0[j] * D1[j]; // нормализуем вектор Div = 0.; for (j = 0; j < SizeArr; ++j) Div += D0[j] * D0[j]; Div = sqrt(Div); for (j = 0; j < SizeArr; ++j) D0[j] /= Div; // сохраняем результат в массив векторов в транспонированном виде (по строкам) for (j = 0; j < SizeArr; ++j) Arr[i][j] = D0[j]; } } void ivm(double **DT, double *D0, size_t SizeArr) { size_t i; // подсчитываем сингулярные значения for (i = 0; i < SizeArr; ++i) D0[i] = (DT[2][i] > 0 ? sqrt(DT[2][i]) : 0); // находим обратную вектор матрицу for (i = 0; i < SizeArr; ++i) D0[i] = 1. / D0[i]; } void vxb(double *V, double **B, double **C, size_t whM, size_t wB) { size_t i, j; for (i = 0; i < whM; ++i) for (j = 0; j < wB; ++j) C[i][j] = V[i] * B[i][j]; } void smdd(double **C, double *D0, size_t SizeArr) { // сортировка строк матрицы по убыванию значений вектор матрицы size_t Pos = 0, i, j; double Max, Swp, *pSwp; for (i = 0; i < SizeArr - 1; ++i) { for (j = i + 1, Max = D0[i]; j < SizeArr; ++j) if (Max < D0[j]) Max = D0[j], Pos = j; if (i != Pos) { Swp = D0[i]; D0[i] = D0[Pos]; D0[Pos] = Swp; pSwp = C[i]; C[i] = C[Pos]; C[Pos] = pSwp; } } } void axb(double **A, double **B, double **C, size_t hA, size_t whM, size_t wB) { for (size_t i = 0; i < hA; ++i) for (size_t j = 0; j < wB; ++j) { C[i][j] = 0.; for (size_t k = 0; k < whM; ++k) C[i][j] += A[i][k] * B[k][j]; } } void output1(double *a, size_t n) { for (size_t x = 0; x < n; ++x) printf("%14.10lf ", a[x]); puts("\n"); } void output2i(double **a, size_t n) { for (size_t y = 0; y < n; ++y) { for (size_t x = 0; x < n; ++x) printf("%5.0lf ", a[y][x]); puts(""); } puts(""); } void output2t(double **a, size_t n) { for (size_t y = 0; y < n; ++y) { for (size_t x = 0; x < n; ++x) printf("%14.10lf ", a[x][y]); puts(""); } puts(""); } void output2r(double **a, size_t n, size_t m) { for (size_t y = 0; y < n; ++y) { for (size_t x = 0; x < m; ++x) printf("%5.0lf ", a[y][x]); puts(""); } puts(""); } void output2rt(double **a, size_t n, size_t m) { for (size_t y = 0; y < n; ++y) { for (size_t x = 0; x < m; ++x) printf("%14.10lf ", a[x][y]); puts(""); } puts(""); }
Решение задачи: «Malloc ошибка освобождения памяти»
textual
Листинг программы
Len = wData * sizeof(**Data); Data = (double**)malloc(SizeArr * sizeof(*Data)); for (i = 0; i < SizeArr; ++i) Data[i] = (double*)malloc(Len); Len = SizeArr * sizeof(double); Arr = (double**)malloc(SizeArr * sizeof(*Arr)); for (i = 0; i < SizeArr; ++i) Arr[i] = (double*)malloc(Len); DT = (double**)malloc(3 * sizeof(*DT)); for (i = 0; i < 3; ++i) DT[i] = (double*)malloc(Len); SU = (double**)malloc(SizeArr * sizeof(*SU)); for (i = 0; i < SizeArr; ++i) SU[i] = (double*)malloc(Len); for (i = 0; i < SizeArr; ++i) free(Data[i]); free(Data); Data = NULL; for (i = 0; i < SizeArr; ++i) free(Arr[i]); free(Arr); Arr = NULL; for (i = 0; i < SizeArr; ++i) free(SU[i]); free(SU); SU = NULL; for (i = 0; i < 3; ++i) free(DT[i]); free(DT); DT = NULL; free(D0); D0 = NULL; free(D1); D1 = NULL;
Объяснение кода листинга программы
- Сначала мы вычисляем размер массива указателей на double, используя оператор sizeof.
- Затем мы используем функцию malloc для выделения памяти под массив указателей на double.
- Далее мы используем цикл for для выделения памяти под каждый элемент массива указателей на double, используя тот же размер, что и ранее.
- Мы повторяем шаги 2 и 3 для других массивов.
- Затем мы освобождаем память, используя функцию free, сначала для массива Data, затем для массива Arr, затем для массива SU, и, наконец, для массива DT.
- Мы также освобождаем память для отдельных double, используя функцию free.
- Наконец, мы устанавливаем указатели на NULL, чтобы освободить память.
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д